a5d0082415dfb1152dc47d7fda94e1cd20ed1a51
2 * firewall3 - 3rd OpenWrt UCI firewall implementation
4 * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 static int lock_fd
= -1;
23 static pid_t pipe_pid
= -1;
24 static FILE *pipe_fd
= NULL
;
27 warn_elem_section_name(struct uci_section
*s
, bool find_name
)
31 struct uci_element
*tmp
;
35 uci_foreach_element(&s
->package
->sections
, tmp
)
37 if (strcmp(uci_to_section(tmp
)->type
, s
->type
))
46 fprintf(stderr
, "@%s[%d]", s
->type
, i
);
50 uci_foreach_element(&s
->options
, tmp
)
52 o
= uci_to_option(tmp
);
54 if (!strcmp(tmp
->name
, "name") && (o
->type
== UCI_TYPE_STRING
))
56 fprintf(stderr
, " (%s)", o
->v
.string
);
64 fprintf(stderr
, "'%s'", s
->e
.name
);
72 warn_elem(struct uci_element
*e
, const char *format
, ...)
74 if (e
->type
== UCI_TYPE_SECTION
)
76 fprintf(stderr
, "Warning: Section ");
77 warn_elem_section_name(uci_to_section(e
), true);
79 else if (e
->type
== UCI_TYPE_OPTION
)
81 fprintf(stderr
, "Warning: Option ");
82 warn_elem_section_name(uci_to_option(e
)->section
, false);
83 fprintf(stderr
, ".%s ", e
->name
);
87 va_start(argptr
, format
);
88 vfprintf(stderr
, format
, argptr
);
91 fprintf(stderr
, "\n");
95 warn(const char* format
, ...)
97 fprintf(stderr
, "Warning: ");
99 va_start(argptr
, format
);
100 vfprintf(stderr
, format
, argptr
);
102 fprintf(stderr
, "\n");
106 error(const char* format
, ...)
108 fprintf(stderr
, "Error: ");
110 va_start(argptr
, format
);
111 vfprintf(stderr
, format
, argptr
);
113 fprintf(stderr
, "\n");
119 info(const char* format
, ...)
122 va_start(argptr
, format
);
123 vfprintf(stderr
, format
, argptr
);
125 fprintf(stderr
, "\n");
129 fw3_find_command(const char *cmd
)
132 int plen
= 0, clen
= strlen(cmd
) + 1;
134 static char path
[PATH_MAX
];
136 if (!stat(cmd
, &s
) && S_ISREG(s
.st_mode
))
139 search
= getenv("PATH");
142 search
= "/bin:/usr/bin:/sbin:/usr/sbin";
148 if (*p
!= ':' && *p
!= '\0')
153 if ((plen
+ clen
) >= sizeof(path
))
156 strncpy(path
, search
, plen
);
157 sprintf(path
+ plen
, "/%s", cmd
);
159 if (!stat(path
, &s
) && S_ISREG(s
.st_mode
))
170 fw3_stdout_pipe(void)
177 __fw3_command_pipe(bool silent
, const char *command
, ...)
183 char *arg
, **args
, **tmp
;
185 command
= fw3_find_command(command
);
194 args
= malloc(argn
* sizeof(arg
));
199 args
[0] = (char *)command
;
202 va_start(argp
, command
);
204 while ((arg
= va_arg(argp
, char *)) != NULL
)
206 tmp
= realloc(args
, ++argn
* sizeof(arg
));
218 switch ((pid
= fork()))
234 execv(command
, args
);
237 signal(SIGPIPE
, SIG_IGN
);
242 pipe_fd
= fdopen(pfds
[1], "w");
247 fw3_pr(const char *fmt
, ...)
251 vfprintf(pipe_fd
, fmt
, args
);
256 fw3_command_close(void)
258 if (pipe_fd
&& pipe_fd
!= stdout
)
262 waitpid(pipe_pid
, NULL
, 0);
264 signal(SIGPIPE
, SIG_DFL
);
271 fw3_has_table(bool ipv6
, const char *table
)
278 const char *path
= ipv6
279 ? "/proc/net/ip6_tables_names" : "/proc/net/ip_tables_names";
281 if (!(f
= fopen(path
, "r")))
284 while (fgets(line
, sizeof(line
), f
))
286 if (!strncmp(line
, table
, strlen(table
)))
302 lock_fd
= open(FW3_LOCKFILE
, O_CREAT
|O_WRONLY
, S_IRUSR
|S_IWUSR
);
306 warn("Cannot create lock file %s: %s", FW3_LOCKFILE
, strerror(errno
));
310 if (flock(lock_fd
, LOCK_EX
))
312 warn("Cannot acquire exclusive lock: %s", strerror(errno
));
325 if (flock(lock_fd
, LOCK_UN
))
326 warn("Cannot release exclusive lock: %s", strerror(errno
));
329 unlink(FW3_LOCKFILE
);
335 bool fw3_has_state(void)
338 return !stat(FW3_STATEFILE
, &s
);
341 void fw3_write_state(void *state
)
345 struct fw3_state
*s
= state
;
349 sf
= fopen(FW3_STATEFILE
, "w");
353 warn("Cannot create state %s: %s", FW3_STATEFILE
, strerror(errno
));
357 list_for_each_entry(z
, &s
->zones
, list
)
359 for (n
= FW3_TARGET_ACCEPT
, val
= 0; n
<= FW3_TARGET_SNAT
; n
++)
360 if (z
->has_src_target
[n
])
363 fprintf(sf
, "zone %s %u", z
->name
, val
);
365 for (n
= FW3_TARGET_ACCEPT
, val
= 0; n
<= FW3_TARGET_SNAT
; n
++)
366 if (z
->has_dest_target
[n
])
369 fprintf(sf
, " %u\n", val
);
372 list_for_each_entry(i
, &s
->ipsets
, list
)
374 if (i
->external
&& *i
->external
)
377 fprintf(sf
, "ipset %s\n", i
->name
);
383 void fw3_remove_state(void)
385 if (unlink(FW3_STATEFILE
))
386 warn("Unable to remove state %s: %s", FW3_STATEFILE
, strerror(errno
));