summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Make_global.am3
-rw-r--r--include/libipset/session.h2
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/libipset.map5
-rw-r--r--lib/session.c13
-rw-r--r--src/ipset.827
-rw-r--r--src/ipset.c61
-rw-r--r--src/ui.c39
8 files changed, 141 insertions, 11 deletions
diff --git a/Make_global.am b/Make_global.am
index 24a1a34..4a8f61a 100644
--- a/Make_global.am
+++ b/Make_global.am
@@ -68,7 +68,8 @@
# as -version-info 2:0:0. This release has a new, but backwards incompatible
# interface.
-LIBVERSION = 2:1:0
+# curr:rev:age
+LIBVERSION = 3:0:1
AM_CPPFLAGS = $(kinclude_CFLAGS) $(all_includes) -I$(top_srcdir)/include \
-I/usr/local/include
diff --git a/include/libipset/session.h b/include/libipset/session.h
index 467bb2f..988233e 100644
--- a/include/libipset/session.h
+++ b/include/libipset/session.h
@@ -97,6 +97,8 @@ extern int ipset_cmd(struct ipset_session *session, enum ipset_cmd cmd,
typedef int (*ipset_outfn)(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
+extern int ipset_session_outfn(struct ipset_session *session,
+ ipset_outfn outfn);
extern struct ipset_session *ipset_session_init(ipset_outfn outfn);
extern int ipset_session_fini(struct ipset_session *session);
diff --git a/lib/Makefile.am b/lib/Makefile.am
index fd853dd..392b5f9 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -19,7 +19,7 @@ lib_LTLIBRARIES = libipset.la
include $(top_srcdir)/lib/Make_extra.am
-libipset_la_LDFLAGS = -Wl,--version-script=$(top_srcdir)/lib/libipset.map -version-info $(LIBVERSION)
+libipset_la_LDFLAGS = -Wl,--version-script=$(top_srcdir)/lib/libipset.map -version-number $(LIBVERSION)
libipset_la_LIBADD = ${libmnl_LIBS} $(IPSET_SETTYPE_STATIC_OBJECTS)
libipset_la_SOURCES = \
data.c \
diff --git a/lib/libipset.map b/lib/libipset.map
index fd6b8c0..74370b2 100644
--- a/lib/libipset.map
+++ b/lib/libipset.map
@@ -117,3 +117,8 @@ global:
ipset_parse_timeout;
ipset_data_test_ignored;
} LIBIPSET_1.0;
+
+LIBIPSET_3.0 {
+global:
+ ipset_session_outfn;
+} LIBIPSET_2.0;
diff --git a/lib/session.c b/lib/session.c
index 6700ea1..3803bfa 100644
--- a/lib/session.c
+++ b/lib/session.c
@@ -1941,6 +1941,19 @@ cleanup:
}
/**
+ * ipset_session_outfn - set session output printing function
+ *
+ * Set the session printing function.
+ *
+ */
+int
+ipset_session_outfn(struct ipset_session *session, ipset_outfn outfn)
+{
+ session->outfn = outfn ? outfn : printf;
+ return 0;
+}
+
+/**
* ipset_session_init - initialize an ipset session
*
* Initialize an ipset session by allocating a session structure
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).",
+ },
{ },
};