summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ipset.827
-rw-r--r--src/ipset.c61
-rw-r--r--src/ui.c39
3 files changed, 118 insertions, 9 deletions
diff --git a/src/ipset.8 b/src/ipset.8
index a2ee39f..d140f3d 100644
--- a/src/ipset.8
+++ b/src/ipset.8
@@ -13,7 +13,7 @@
.\" You should have received a copy of the GNU General Public License
.\" along with this program; if not, write to the Free Software
.\" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-.TH "IPSET" "8" "Oct 15, 2010" "Jozsef Kadlecsik" ""
+.TH "IPSET" "8" "May 23, 2012" "Jozsef Kadlecsik" ""
.SH "NAME"
ipset \(em administration tool for IP sets
.SH "SYNOPSIS"
@@ -21,7 +21,7 @@ ipset \(em administration tool for IP sets
.PP
COMMANDS := { \fBcreate\fR | \fBadd\fR | \fBdel\fR | \fBtest\fR | \fBdestroy\fR | \fBlist\fR | \fBsave\fR | \fBrestore\fR | \fBflush\fR | \fBrename\fR | \fBswap\fR | \fBhelp\fR | \fBversion\fR | \fB\-\fR }
.PP
-\fIOPTIONS\fR := { \fB\-exist\fR | \fB\-output\fR { \fBplain\fR | \fBsave\fR | \fBxml\fR } | \fB\-quiet\fR | \fB\-resolve\fR | \fB\-sorted\fR | \fB\-name\fR | \fB\-terse\fR }
+\fIOPTIONS\fR := { \fB\-exist\fR | \fB\-output\fR { \fBplain\fR | \fBsave\fR | \fBxml\fR } | \fB\-quiet\fR | \fB\-resolve\fR | \fB\-sorted\fR | \fB\-name\fR | \fB\-terse\fR | \fB\-file\fR \fIfilename\fR }
.PP
\fBipset\fR \fBcreate\fR \fISETNAME\fR \fITYPENAME\fR [ \fICREATE\-OPTIONS\fR ]
.PP
@@ -126,18 +126,25 @@ If the option
\fB\-name\fR
is specified, just the names of the existing sets are listed. If the option
\fB\-terse\fR
-is specified, just the set names and headers are listed.
+is specified, just the set names and headers are listed. The output is printed
+to stdout, the option
+\fB\-file\fR
+can be used to specify a filename instead of stdout.
.TP
\fBsave\fP [ \fISETNAME\fP ]
Save the given set, or all sets if none is given
to stdout in a format that
\fBrestore\fP
-can read.
+can read. The option
+\fB\-file\fR
+can be used to specify a filename instead of stdout.
.TP
\fBrestore\fP
Restore a saved session generated by
\fBsave\fP.
-The saved session can be fed from stdin.
+The saved session can be fed from stdin or the option
+\fB\-file\fR
+can be used to specify a filename instead of stdin.
.TP
\fBflush\fP [ \fISETNAME\fP ]
Flush all entries from the specified set or flush
@@ -201,7 +208,15 @@ List just the names of the existing sets, i.e. suppress listing of set headers a
.TP
\fB\-t\fP, \fB\-terse\fP
List the set names and headers, i.e. suppress listing of set members.
-
+.TP
+\fB\-f\fP, \fB\-file\fP \fIfilename\fR
+Specidy a filename to print into instead of stdout
+(\fBlist\fR
+or
+\fBsave\fR
+commands) or read from instead of stdin
+(\fBrestore\fR
+command).
.SH "SET TYPES"
A set type comprises of the storage method by which the data is stored and
the data type(s) which are stored in the set. Therefore the
diff --git a/src/ipset.c b/src/ipset.c
index 4a20ca1..8e5411f 100644
--- a/src/ipset.c
+++ b/src/ipset.c
@@ -6,7 +6,9 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#include <assert.h> /* assert */
#include <ctype.h> /* isspace */
+#include <errno.h> /* errno */
#include <stdarg.h> /* va_* */
#include <stdbool.h> /* bool */
#include <stdio.h> /* fprintf, fgets */
@@ -32,6 +34,8 @@ static bool interactive;
static char cmdline[1024];
static char *newargv[255];
static int newargc;
+static FILE *fd = NULL;
+static const char *filename = NULL;
enum exittype {
NO_PROBLEM = 0,
@@ -74,6 +78,8 @@ exit_error(int status, const char *msg, ...)
ipset_session_fini(session);
D("status: %u", status);
+ if (fd)
+ fclose(fd);
exit(status > VERSION_PROBLEM ? OTHER_PROBLEM : status);
/* Unreached */
return -1;
@@ -92,6 +98,8 @@ handle_error(void)
if (!interactive) {
ipset_session_fini(session);
+ if (fd)
+ fclose(fd);
exit(OTHER_PROBLEM);
}
@@ -120,6 +128,32 @@ help(void)
}
}
+int
+ipset_parse_file(struct ipset_session *session UNUSED,
+ int opt UNUSED, const char *str)
+{
+ if (filename != NULL)
+ return exit_error(PARAMETER_PROBLEM,
+ "-file option can be specified once");
+ filename = str;
+
+ return 0;
+}
+
+int __attribute__ ((format (printf, 1, 2)))
+ipset_print_file(const char *fmt, ...)
+{
+ int len;
+ va_list args;
+
+ assert(fd != NULL);
+ va_start(args, fmt);
+ len = vfprintf(fd, fmt, args);
+ va_end(args);
+
+ return len;
+}
+
/* Build faked argv from parsed line */
static void
build_argv(char *buffer)
@@ -156,12 +190,22 @@ restore(char *argv0)
{
int ret = 0;
char *c;
+ FILE *fread = stdin;
/* Initialize newargv/newargc */
newargc = 0;
newargv[newargc++] = argv0;
+ if (filename) {
+ fd = fopen(filename, "r");
+ if (!fd) {
+ return exit_error(OTHER_PROBLEM,
+ "Cannot open %s for reading: %s",
+ filename, strerror(errno));
+ }
+ fread = fd;
+ }
- while (fgets(cmdline, sizeof(cmdline), stdin)) {
+ while (fgets(cmdline, sizeof(cmdline), fread)) {
restore_line++;
c = cmdline;
while (isspace(c[0]))
@@ -624,10 +668,19 @@ parse_commandline(int argc, char *argv[])
check_allowed(type, cmd);
break;
- case IPSET_CMD_DESTROY:
- case IPSET_CMD_FLUSH:
case IPSET_CMD_LIST:
case IPSET_CMD_SAVE:
+ if (filename != NULL) {
+ fd = fopen(filename, "w");
+ if (!fd)
+ return exit_error(OTHER_PROBLEM,
+ "Cannot open %s for writing: "
+ "%s", filename,
+ strerror(errno));
+ ipset_session_outfn(session, ipset_print_file);
+ }
+ case IPSET_CMD_DESTROY:
+ case IPSET_CMD_FLUSH:
/* Args: [setname] */
if (arg0) {
ret = ipset_parse_setname(session,
@@ -721,6 +774,8 @@ main(int argc, char *argv[])
ret = parse_commandline(argc, argv);
ipset_session_fini(session);
+ if (fd)
+ fclose(fd);
return ret;
}
diff --git a/src/ui.c b/src/ui.c
index 7e40bde..0ebacbb 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -154,6 +154,37 @@ ipset_match_cmd(const char *arg, const char * const name[])
(name[1] != NULL && tolower(arg[0]) == name[1][0]);
}
+/* Used up so far
+ *
+ * -A add
+ * -D del
+ * -E rename
+ * -f -file
+ * -F flush
+ * -h help
+ * -H help
+ * -L list
+ * -n -name
+ * -N create
+ * -o -output
+ * -r -resolve
+ * -R restore
+ * -s -sorted
+ * -S save
+ * -t -terse
+ * -T test
+ * -q -quiet
+ * -X destroy
+ * -v version
+ * -V version
+ * -W swap
+ * -! -exist
+ */
+
+int
+ipset_parse_file(struct ipset_session *session,
+ int opt, const char *str);
+
const struct ipset_envopts ipset_envopts[] = {
{ .name = { "-o", "-output" },
.has_arg = IPSET_MANDATORY_ARG, .flag = IPSET_OPT_MAX,
@@ -202,6 +233,14 @@ const struct ipset_envopts ipset_envopts[] = {
" When listing, list setnames and set headers\n"
" from kernel only.",
},
+ { .name = { "-f", "-file" },
+ .parse = ipset_parse_file,
+ .has_arg = IPSET_MANDATORY_ARG, .flag = IPSET_OPT_MAX,
+ .help = "\n"
+ " Read from the given file instead of standard\n"
+ " input (restore) or write to given file instead\n"
+ " of standard output (list/save).",
+ },
{ },
};