2 * ebtablesd.c, January 2005
4 * Author: Bart De Schuymer
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <sys/types.h>
30 #include "include/ebtables_u.h"
32 #define OPT_KERNELDATA 0x800 /* Also defined in ebtables.c */
34 static struct ebt_u_replace replace
[3];
35 #define OPEN_METHOD_FILE 1
36 #define OPEN_METHOD_KERNEL 2
37 static int open_method
[3];
38 void ebt_early_init_once();
40 static void sigpipe_handler(int sig
)
43 static void copy_table_names()
45 strcpy(replace
[0].name
, "filter");
46 strcpy(replace
[1].name
, "nat");
47 strcpy(replace
[2].name
, "broute");
50 int main(int argc_
, char *argv_
[])
52 char *argv
[EBTD_ARGC_MAX
], *args
[4], name
[] = "mkdir",
53 mkdir_option
[] = "-p", mkdir_dir
[] = EBTD_PIPE_DIR
,
54 cmdline
[EBTD_CMDLINE_MAXLN
];
55 int readfd
, base
= 0, offset
= 0, n
= 0, ret
= 0, quotemode
= 0;
57 /* Make sure the pipe directory exists */
59 args
[1] = mkdir_option
;
64 execvp(args
[0], args
);
66 /* Not usually reached */
75 if (mkfifo(EBTD_PIPE
, 0600) < 0 && errno
!= EEXIST
) {
76 printf("Error creating FIFO " EBTD_PIPE
"\n");
81 if ((readfd
= open(EBTD_PIPE
, O_RDONLY
| O_NONBLOCK
, 0)) == -1) {
87 if (signal(SIGPIPE
, sigpipe_handler
) == SIG_ERR
) {
96 ebt_early_init_once();
99 int n2
, i
, argc
, table_nr
, ntot
;
102 ntot
= read(readfd
, cmdline
+offset
, EBTD_CMDLINE_MAXLN
-offset
-1);
107 /* Put '\0' between arguments. */
108 for (; offset
< ntot
; n
++, offset
++) {
109 if (cmdline
[offset
] == '\"') {
111 cmdline
[offset
] = '\0';
112 } else if (!quotemode
&& cmdline
[offset
] == ' ') {
113 cmdline
[offset
] = '\0';
114 } else if (cmdline
[offset
] == '\n') {
116 ebt_print_error("ebtablesd: wrong number of \" delimiters");
117 cmdline
[offset
] = '\0';
122 if (offset
== ntot
) {
123 /* The ntot bytes were parsed and ended with '\n' */
133 if (offset
== ntot
) { /* The ntot bytes were parsed but no complete rule is yet specified */
135 ebt_print_error("ebtablesd: the maximum command line length is %d", EBTD_CMDLINE_MAXLN
-1);
138 memmove(cmdline
, cmdline
+base
+offset
, ntot
-offset
);
148 while (n2
< n
&& argc
< EBTD_ARGC_MAX
) {
149 if (*(cmdline
+ base
+ n2
) == '\0') {
153 argv
[argc
++] = cmdline
+ base
+ n2
;
154 n2
+= strlen(cmdline
+ base
+ n2
) + 1;
156 offset
++; /* Move past the '\n' */
159 if (argc
> EBTD_ARGC_MAX
) {
160 ebt_print_error("ebtablesd: maximum %d arguments "
161 "allowed", EBTD_ARGC_MAX
- 1);
165 ebt_print_error("ebtablesd: no arguments");
169 /* Parse the options */
170 if (!strcmp(argv
[1], "-t")) {
172 ebt_print_error("ebtablesd: -t but no table");
175 for (i
= 0; i
< 3; i
++)
176 if (!strcmp(replace
[i
].name
, argv
[2]))
179 ebt_print_error("ebtablesd: table '%s' was "
180 "not recognized", argv
[2]);
184 } else if (!strcmp(argv
[1], "free")) {
186 ebt_print_error("ebtablesd: command free "
187 "needs exactly one argument");
190 for (i
= 0; i
< 3; i
++)
191 if (!strcmp(replace
[i
].name
, argv
[2]))
194 ebt_print_error("ebtablesd: table '%s' was "
195 "not recognized", argv
[2]);
198 if (!(replace
[i
].flags
& OPT_KERNELDATA
)) {
199 ebt_print_error("ebtablesd: table %s has not "
203 ebt_cleanup_replace(&replace
[i
]);
205 replace
[i
].flags
&= ~OPT_KERNELDATA
;
207 } else if (!strcmp(argv
[1], "open")) {
209 ebt_print_error("ebtablesd: command open "
210 "needs exactly one argument");
214 for (i
= 0; i
< 3; i
++)
215 if (!strcmp(replace
[i
].name
, argv
[2]))
218 ebt_print_error("ebtablesd: table '%s' was "
219 "not recognized", argv
[2]);
222 if (replace
[i
].flags
& OPT_KERNELDATA
) {
223 ebt_print_error("ebtablesd: table %s needs to "
224 "be freed before it can be "
228 if (!ebt_get_kernel_table(&replace
[i
], 0)) {
229 replace
[i
].flags
|= OPT_KERNELDATA
;
230 open_method
[i
] = OPEN_METHOD_KERNEL
;
233 } else if (!strcmp(argv
[1], "fopen")) {
234 struct ebt_u_replace tmp
;
236 memset(&tmp
, 0, sizeof(tmp
));
238 ebt_print_error("ebtablesd: command fopen "
239 "needs exactly two arguments");
243 for (i
= 0; i
< 3; i
++)
244 if (!strcmp(replace
[i
].name
, argv
[2]))
247 ebt_print_error("ebtablesd: table '%s' was "
248 "not recognized", argv
[2]);
251 if (replace
[i
].flags
& OPT_KERNELDATA
) {
252 ebt_print_error("ebtablesd: table %s needs to "
253 "be freed before it can be "
257 tmp
.filename
= (char *)malloc(strlen(argv
[3]) + 1);
259 ebt_print_error("Out of memory");
262 strcpy(tmp
.filename
, argv
[3]);
263 strcpy(tmp
.name
, "filter");
264 tmp
.command
= 'L'; /* Make sure retrieve_from_file()
265 * doesn't complain about wrong
268 ebt_get_kernel_table(&tmp
, 0);
271 if (ebt_errormsg
[0] != '\0')
274 if (strcmp(tmp
.name
, argv
[2])) {
275 ebt_print_error("ebtablesd: opened file with "
276 "wrong table name '%s'", tmp
.name
);
277 ebt_cleanup_replace(&tmp
);
281 replace
[i
].command
= '\0';
282 replace
[i
].flags
|= OPT_KERNELDATA
;
283 open_method
[i
] = OPEN_METHOD_FILE
;
285 } else if (!strcmp(argv
[1], "commit")) {
287 ebt_print_error("ebtablesd: command commit "
288 "needs exactly one argument");
292 for (i
= 0; i
< 3; i
++)
293 if (!strcmp(replace
[i
].name
, argv
[2]))
296 ebt_print_error("ebtablesd: table '%s' was "
297 "not recognized", argv
[2]);
300 if (!(replace
[i
].flags
& OPT_KERNELDATA
)) {
301 ebt_print_error("ebtablesd: table %s has not "
305 /* The counters from the kernel are useless if we
306 * didn't start from a kernel table */
307 if (open_method
[i
] == OPEN_METHOD_FILE
)
308 replace
[i
].num_counters
= 0;
309 ebt_deliver_table(&replace
[i
]);
310 if (ebt_errormsg
[0] == '\0' && open_method
[i
] == OPEN_METHOD_KERNEL
)
311 ebt_deliver_counters(&replace
[i
]);
313 } else if (!strcmp(argv
[1], "fcommit")) {
315 ebt_print_error("ebtablesd: command commit "
316 "needs exactly two argument");
320 for (i
= 0; i
< 3; i
++)
321 if (!strcmp(replace
[i
].name
, argv
[2]))
324 ebt_print_error("ebtablesd: table '%s' was "
325 "not recognized", argv
[2]);
328 if (!(replace
[i
].flags
& OPT_KERNELDATA
)) {
329 ebt_print_error("ebtablesd: table %s has not "
333 replace
[i
].filename
= (char *)malloc(strlen(argv
[3]) + 1);
334 if (!replace
[i
].filename
) {
335 ebt_print_error("Out of memory");
338 strcpy(replace
[i
].filename
, argv
[3]);
339 ebt_deliver_table(&replace
[i
]);
340 if (ebt_errormsg
[0] == '\0' && open_method
[i
] == OPEN_METHOD_KERNEL
)
341 ebt_deliver_counters(&replace
[i
]);
342 free(replace
[i
].filename
);
343 replace
[i
].filename
= NULL
;
345 }else if (!strcmp(argv
[1], "quit")) {
347 ebt_print_error("ebtablesd: command quit does "
348 "not take any arguments");
353 if (!(replace
[table_nr
].flags
& OPT_KERNELDATA
)) {
354 ebt_print_error("ebtablesd: table %s has not been "
355 "opened", replace
[table_nr
].name
);
358 optind
= 0; /* Setting optind = 1 causes serious annoyances */
359 do_command(argc
, argv
, EXEC_STYLE_DAEMON
, &replace
[table_nr
]);
360 ebt_reinit_extensions();
362 #ifndef SILENT_DAEMON
363 if (ebt_errormsg
[0] != '\0')
364 printf("%s.\n", ebt_errormsg
);
366 ebt_errormsg
[0]= '\0';