1 /* Copyright 2000-2002 Joakim Axelsson (gozem@linux.nu)
2 * Patrick Schaaf (bof@bof.de)
3 * Copyright 2003-2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
10 #include <stdio.h> /* *printf, perror, sscanf, fdopen */
11 #include <string.h> /* mem*, str* */
12 #include <errno.h> /* errno, perror */
13 #include <time.h> /* time, ctime */
14 #include <netdb.h> /* gethostby*, getnetby*, getservby* */
15 #include <stdlib.h> /* exit, malloc, free, strtol, getenv, mkstemp */
16 #include <unistd.h> /* read, close, fork, exec*, unlink */
17 #include <sys/types.h> /* open, wait, socket, *sockopt, umask */
18 #include <sys/stat.h> /* open, umask */
19 #include <sys/wait.h> /* wait */
20 #include <sys/socket.h> /* socket, *sockopt, gethostby*, inet_* */
21 #include <netinet/in.h> /* inet_* */
22 #include <fcntl.h> /* open */
23 #include <arpa/inet.h> /* htonl, inet_* */
24 #include <stdarg.h> /* va_* */
25 #include <dlfcn.h> /* dlopen */
29 #ifndef PROC_SYS_MODPROBE
30 #define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
33 char program_name
[] = "ipset";
34 char program_version
[] = IPSET_VERSION
;
35 static int protocol_version
= 0;
37 #define STREQ(a,b) (strncmp(a,b,IP_SET_MAXNAMELEN) == 0)
38 #define DONT_ALIGN (protocol_version == IP_SET_PROTOCOL_UNALIGNED)
39 #define ALIGNED(len) IPSET_VALIGN(len, DONT_ALIGN)
41 /* The list of loaded set types */
42 static struct settype
*all_settypes
= NULL
;
45 struct set
**set_list
= NULL
;
46 ip_set_id_t max_sets
= 0;
48 /* Suppress output to stdout and stderr? */
49 static int option_quiet
= 0;
51 /* Data for restore mode */
52 static int restore
= 0;
53 void *restore_data
= NULL
;
54 struct ip_set_restore
*restore_set
= NULL
;
55 size_t restore_offset
= 0;
56 socklen_t restore_size
;
57 unsigned restore_line
= 0;
58 unsigned warn_once
= 0;
60 #define TEMPFILE_PATTERN "/ipsetXXXXXX"
66 #define OPTION_OFFSET 256
67 static unsigned int global_option_offset
= 0;
69 /* Most of these command parsing functions are borrowed from iptables.c */
71 static const char cmdflags
[] = { ' ', /* CMD_NONE */
72 'N', 'X', 'F', 'E', 'W', 'L', 'S', 'R',
73 'A', 'D', 'T', 'H', 'V',
77 #define OPT_NONE 0x0000U
78 #define OPT_NUMERIC 0x0001U /* -n */
79 #define OPT_SORTED 0x0002U /* -s */
80 #define OPT_QUIET 0x0004U /* -q */
81 #define OPT_DEBUG 0x0008U /* -z */
82 #define OPT_RESOLVE 0x0020U /* -r */
83 #define NUMBER_OF_OPT 5
84 static const char optflags
[] =
85 { 'n', 's', 'q', 'z', 'r' };
87 static struct option opts_long
[] = {
89 {"create", 1, 0, 'N'},
90 {"destroy", 2, 0, 'X'},
92 {"rename", 1, 0, 'E'},
97 {"restore", 0, 0, 'R'},
99 /* ip in set operations */
105 {"numeric", 0, 0, 'n'},
106 {"sorted", 0, 0, 's'},
107 {"quiet", 0, 0, 'q'},
108 {"resolve", 0, 0, 'r'},
111 /* debug (if compiled with it) */
112 {"debug", 0, 0, 'z'},
115 /* version and help */
116 {"version", 0, 0, 'V'},
123 static char opts_short
[] =
124 "-N:X::F::E:W:L::S::RA:D:T:nrsqzvVh::H::";
126 /* Table of legal combinations of commands and options. If any of the
127 * given commands make an option legal, that option is legal.
134 static char commands_v_options
[NUMBER_OF_CMD
][NUMBER_OF_OPT
] = {
136 /*CREATE*/ {'x', 'x', ' ', ' ', 'x'},
137 /*DESTROY*/ {'x', 'x', ' ', ' ', 'x'},
138 /*FLUSH*/ {'x', 'x', ' ', ' ', 'x'},
139 /*RENAME*/ {'x', 'x', ' ', ' ', 'x'},
140 /*SWAP*/ {'x', 'x', ' ', ' ', 'x'},
141 /*LIST*/ {' ', ' ', 'x', ' ', ' '},
142 /*SAVE*/ {'x', 'x', ' ', ' ', 'x'},
143 /*RESTORE*/ {'x', 'x', ' ', ' ', 'x'},
144 /*ADD*/ {'x', 'x', ' ', ' ', 'x'},
145 /*DEL*/ {'x', 'x', ' ', ' ', 'x'},
146 /*TEST*/ {'x', 'x', ' ', ' ', 'x'},
147 /*HELP*/ {'x', 'x', 'x', ' ', 'x'},
148 /*VERSION*/ {'x', 'x', 'x', ' ', 'x'},
151 /* Main parser function */
152 int parse_commandline(int argc
, char *argv
[]);
154 static void exit_tryhelp(int status
)
157 "Try `%s -H' or '%s --help' for more information.\n",
158 program_name
, program_name
);
162 void exit_error(int status
, const char *msg
, ...)
168 fprintf(stderr
, "%s v%s: ", program_name
, program_version
);
169 vfprintf(stderr
, msg
, args
);
171 fprintf(stderr
, "\n");
173 fprintf(stderr
, "Restore failed at line %u:\n", restore_line
);
174 if (status
== PARAMETER_PROBLEM
)
175 exit_tryhelp(status
);
176 if (status
== VERSION_PROBLEM
)
178 "Perhaps %s or your kernel needs to be upgraded.\n",
185 static void ipset_printf(const char *msg
, ...)
191 vfprintf(stdout
, msg
, args
);
193 fprintf(stdout
, "\n");
197 static void generic_opt_check(int command
, unsigned int options
)
201 /* Check that commands are valid with options. Complicated by the
202 * fact that if an option is legal with *any* command given, it is
203 * legal overall (ie. -z and -l).
205 for (i
= 0; i
< NUMBER_OF_OPT
; i
++) {
206 legal
= 0; /* -1 => illegal, 1 => legal, 0 => undecided. */
208 for (j
= 1; j
<= NUMBER_OF_CMD
; j
++) {
212 if (!(options
& (1 << i
))) {
213 if (commands_v_options
[j
-1][i
] == '+')
214 exit_error(PARAMETER_PROBLEM
,
215 "You need to supply the `-%c' "
216 "option for this command\n",
219 if (commands_v_options
[j
-1][i
] != 'x')
226 exit_error(PARAMETER_PROBLEM
,
227 "Illegal option `-%c' with this command\n",
232 static char opt2char(unsigned int option
)
235 for (ptr
= optflags
; option
> 1; option
>>= 1, ptr
++);
240 static char cmd2char(int cmd
)
242 if (cmd
<= CMD_NONE
|| cmd
> NUMBER_OF_CMD
)
245 return cmdflags
[cmd
];
248 /* From iptables.c ... */
249 static char *get_modprobe(void)
254 #define PROCFILE_BUFSIZ 1024
255 procfile
= open(PROC_SYS_MODPROBE
, O_RDONLY
);
259 ret
= (char *) malloc(PROCFILE_BUFSIZ
);
261 memset(ret
, 0, PROCFILE_BUFSIZ
);
262 switch (read(procfile
, ret
, PROCFILE_BUFSIZ
)) {
264 case PROCFILE_BUFSIZ
: goto fail
; /* Partial read. Wierd */
265 default: ; /* nothing */
267 if (ret
[strlen(ret
)-1]=='\n')
268 ret
[strlen(ret
)-1]=0;
278 static int ipset_insmod(const char *modname
, const char *modprobe
)
285 if (!stat(modprobe
, &junk
)) {
286 /* Try to read out of the kernel */
287 buf
= get_modprobe();
295 argv
[0] = (char *) modprobe
;
296 argv
[1] = (char *) modname
;
298 execv(argv
[0], argv
);
300 /* Should not reach */
305 default: /* parent */
311 if (WIFEXITED(status
) && WEXITSTATUS(status
) == 0)
316 static int kernel_getsocket(void)
320 sockfd
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
);
322 exit_error(OTHER_PROBLEM
,
323 "You need to be root to perform this command.");
328 static void kernel_error(unsigned cmd
, int err
)
331 struct translate_error
{
336 { /* Generic error codes */
337 { EPERM
, 0, "Missing capability" },
338 { EBADF
, 0, "Invalid socket option" },
339 { EINVAL
, 0, "Size mismatch for expected socket data" },
340 { ENOMEM
, 0, "Not enough memory" },
341 { EFAULT
, 0, "Failed to copy data" },
342 { EPROTO
, 0, "ipset kernel/userspace version mismatch" },
343 { EBADMSG
, 0, "Unknown command" },
344 /* Per command error codes */
345 /* Reserved ones for add/del/test to handle internally:
348 { ENOENT
, CMD_CREATE
, "Unknown set type" },
349 { ENOENT
, 0, "Unknown set" },
350 { EAGAIN
, 0, "Sets are busy, try again later" },
351 { ERANGE
, CMD_CREATE
, "No free slot remained to add a new set" },
352 { ERANGE
, 0, "IP/port/element is outside of the set or set is full" },
353 { ENOEXEC
, CMD_CREATE
, "Invalid parameters to create a set" },
354 { ENOEXEC
, CMD_SWAP
, "Sets with different types cannot be swapped" },
355 { EEXIST
, CMD_CREATE
, "Set already exists" },
356 { EEXIST
, CMD_RENAME
, "Set with new name already exists" },
357 { EEXIST
, 0, "Set specified as element does not exist" },
358 { EBUSY
, 0, "Set is in use, operation not permitted" },
360 for (i
= 0; i
< sizeof(table
)/sizeof(struct translate_error
); i
++) {
361 if ((table
[i
].cmd
== cmd
|| table
[i
].cmd
== 0)
362 && table
[i
].err
== err
)
363 exit_error(err
== EPROTO
? VERSION_PROBLEM
367 exit_error(OTHER_PROBLEM
, "Error from kernel: %s", strerror(err
));
370 static inline int wrapped_getsockopt(void *data
, socklen_t
*size
)
373 int sockfd
= kernel_getsocket();
376 res
= getsockopt(sockfd
, SOL_IP
, SO_IP_SET
, data
, size
);
378 && errno
== ENOPROTOOPT
379 && ipset_insmod("ip_set", "/sbin/modprobe") == 0)
380 res
= getsockopt(sockfd
, SOL_IP
, SO_IP_SET
, data
, size
);
381 DP("res=%d errno=%d", res
, errno
);
386 static inline int wrapped_setsockopt(void *data
, socklen_t size
)
389 int sockfd
= kernel_getsocket();
392 res
= setsockopt(sockfd
, SOL_IP
, SO_IP_SET
, data
, size
);
394 && errno
== ENOPROTOOPT
395 && ipset_insmod("ip_set", "/sbin/modprobe") == 0)
396 res
= setsockopt(sockfd
, SOL_IP
, SO_IP_SET
, data
, size
);
397 DP("res=%d errno=%d", res
, errno
);
402 static void kernel_getfrom(unsigned cmd
, void *data
, socklen_t
* size
)
404 int res
= wrapped_getsockopt(data
, size
);
407 kernel_error(cmd
, errno
);
410 static int kernel_sendto_handleerrno(unsigned cmd
,
411 void *data
, socklen_t size
)
413 int res
= wrapped_setsockopt(data
, size
);
419 kernel_error(cmd
, errno
);
422 return 0; /* all ok */
425 static void kernel_sendto(unsigned cmd
, void *data
, size_t size
)
427 int res
= wrapped_setsockopt(data
, size
);
430 kernel_error(cmd
, errno
);
433 static int kernel_getfrom_handleerrno(unsigned cmd
, void *data
, socklen_t
*size
)
435 int res
= wrapped_getsockopt(data
, size
);
441 kernel_error(cmd
, errno
);
444 return 0; /* all ok */
447 static void check_protocolversion(void)
449 struct ip_set_req_version req_version
;
450 socklen_t size
= sizeof(struct ip_set_req_version
);
453 if (protocol_version
)
456 req_version
.op
= IP_SET_OP_VERSION
;
457 res
= wrapped_getsockopt(&req_version
, &size
);
460 exit_error(OTHER_PROBLEM
,
461 "Couldn't verify kernel module version!");
463 if (!(req_version
.version
== IP_SET_PROTOCOL_VERSION
464 || req_version
.version
== IP_SET_PROTOCOL_UNALIGNED
))
465 exit_error(OTHER_PROBLEM
,
466 "Kernel ip_set module is of protocol version %u."
467 "I'm of protocol version %u.\n"
468 "Please upgrade your kernel and/or ipset(8) utillity.",
469 req_version
.version
, IP_SET_PROTOCOL_VERSION
);
470 protocol_version
= req_version
.version
;
473 static void set_command(int *cmd
, int newcmd
)
475 if (*cmd
!= CMD_NONE
)
476 exit_error(PARAMETER_PROBLEM
, "Can't use -%c with -%c\n",
477 cmd2char(*cmd
), cmd2char(newcmd
));
481 static void add_option(unsigned int *options
, unsigned int option
)
483 if (*options
& option
)
484 exit_error(PARAMETER_PROBLEM
,
485 "multiple -%c flags not allowed",
490 void *ipset_malloc(size_t size
)
497 if ((p
= malloc(size
)) == NULL
) {
498 perror("ipset: not enough memory");
504 char *ipset_strdup(const char *s
)
508 if ((p
= strdup(s
)) == NULL
) {
509 perror("ipset: not enough memory");
515 void ipset_free(void *data
)
523 static struct option
*merge_options(struct option
*oldopts
,
524 const struct option
*newopts
,
527 unsigned int num_old
, num_new
, i
;
528 struct option
*merge
;
530 for (num_old
= 0; oldopts
[num_old
].name
; num_old
++);
531 for (num_new
= 0; newopts
[num_new
].name
; num_new
++);
533 global_option_offset
+= OPTION_OFFSET
;
534 *option_offset
= global_option_offset
;
536 merge
= ipset_malloc(sizeof(struct option
) * (num_new
+ num_old
+ 1));
537 memcpy(merge
, oldopts
, num_old
* sizeof(struct option
));
538 for (i
= 0; i
< num_new
; i
++) {
539 merge
[num_old
+ i
] = newopts
[i
];
540 merge
[num_old
+ i
].val
+= *option_offset
;
542 memset(merge
+ num_old
+ num_new
, 0, sizeof(struct option
));
547 static char *ip_tohost(const struct in_addr
*addr
)
549 struct hostent
*host
;
551 if ((host
= gethostbyaddr((char *) addr
,
552 sizeof(struct in_addr
),
554 DP("%s", host
->h_name
);
555 return (char *) host
->h_name
;
558 return (char *) NULL
;
561 static char *ip_tonetwork(const struct in_addr
*addr
)
565 if ((net
= getnetbyaddr(ntohl(addr
->s_addr
),
567 DP("%s", net
->n_name
);
568 return (char *) net
->n_name
;
571 return (char *) NULL
;
574 /* Return a string representation of an IP address.
575 * Please notice that a pointer to static char* area is returned.
577 char *ip_tostring(ip_set_ip_t ip
, unsigned options
)
580 addr
.s_addr
= htonl(ip
);
582 if (!(options
& OPT_NUMERIC
)) {
584 if ((name
= ip_tohost(&addr
)) != NULL
||
585 (name
= ip_tonetwork(&addr
)) != NULL
)
589 return inet_ntoa(addr
);
592 char *ip_tostring_numeric(ip_set_ip_t ip
)
594 return ip_tostring(ip
, OPT_NUMERIC
);
597 /* Fills the 'ip' with the parsed ip or host in host byte order */
598 void parse_ip(const char *str
, ip_set_ip_t
* ip
)
600 struct hostent
*host
;
605 if (inet_aton(str
, &addr
) != 0) {
606 *ip
= ntohl(addr
.s_addr
); /* We want host byte order */
610 host
= gethostbyname(str
);
612 if (host
->h_addrtype
!= AF_INET
||
613 host
->h_length
!= sizeof(struct in_addr
))
614 exit_error(PARAMETER_PROBLEM
,
615 "host/network `%s' not an internet name",
617 if (host
->h_addr_list
[1] != 0)
618 exit_error(PARAMETER_PROBLEM
,
619 "host/network `%s' resolves to serveral ip-addresses. "
620 "Please specify one.", str
);
622 memcpy(&addr
, host
->h_addr_list
[0], sizeof(struct in_addr
));
623 *ip
= ntohl(addr
.s_addr
);
627 exit_error(PARAMETER_PROBLEM
, "host/network `%s' not found", str
);
630 /* Fills 'mask' with the parsed mask in host byte order */
631 void parse_mask(const char *str
, ip_set_ip_t
* mask
)
639 /* no mask at all defaults to 32 bits */
643 if (strchr(str
, '.') && inet_aton(str
, &addr
) != 0) {
644 *mask
= ntohl(addr
.s_addr
); /* We want host byte order */
647 if (sscanf(str
, "%d", &bits
) != 1 || bits
< 0 || bits
> 32)
648 exit_error(PARAMETER_PROBLEM
,
649 "invalid mask `%s' specified", str
);
651 DP("bits: %d", bits
);
653 *mask
= bits
!= 0 ? 0xFFFFFFFF << (32 - bits
) : 0L;
656 /* Combines parse_ip and parse_mask */
658 parse_ipandmask(const char *str
, ip_set_ip_t
* ip
, ip_set_ip_t
* mask
)
663 strncpy(buf
, str
, sizeof(buf
) - 1);
666 if ((p
= strrchr(buf
, '/')) != NULL
) {
668 parse_mask(p
+ 1, mask
);
670 parse_mask(NULL
, mask
);
672 /* if a null mask is given, the name is ignored, like in "any/0" */
678 DP("%s ip: %08X (%s) mask: %08X",
679 str
, *ip
, ip_tostring_numeric(*ip
), *mask
);
681 /* Apply the netmask */
684 DP("%s ip: %08X (%s) mask: %08X",
685 str
, *ip
, ip_tostring_numeric(*ip
), *mask
);
688 /* Return a string representation of a port
689 * Please notice that a pointer to static char* area is returned
690 * and we assume TCP protocol.
692 char *port_tostring(ip_set_ip_t port
, unsigned options
)
694 struct servent
*service
;
695 static char name
[] = "65535";
697 if (!(options
& OPT_NUMERIC
)) {
698 if ((service
= getservbyport(htons(port
), "tcp")))
699 return service
->s_name
;
701 sprintf(name
, "%u", port
);
706 string_to_number(const char *str
, unsigned int min
, unsigned int max
,
709 unsigned long number
;
712 /* Handle hex, octal, etc. */
714 number
= strtoul(str
, &end
, 0);
715 if (*end
== '\0' && end
!= str
) {
716 /* we parsed a number, let's see if we want this */
717 if (errno
!= ERANGE
&& min
<= number
&& number
<= max
) {
726 string_to_port(const char *str
, ip_set_ip_t
*port
)
728 struct servent
*service
;
730 if ((service
= getservbyname(str
, "tcp")) != NULL
) {
731 *port
= ntohs((uint16_t) service
->s_port
);
737 /* Fills the 'ip' with the parsed port in host byte order */
738 void parse_port(const char *str
, ip_set_ip_t
*port
)
740 if ((string_to_number(str
, 0, 65535, port
) != 0)
741 && (string_to_port(str
, port
) != 0))
742 exit_error(PARAMETER_PROBLEM
,
743 "Invalid TCP port `%s' specified", str
);
749 static struct settype
*settype_find(const char *typename
)
751 struct settype
*runner
= all_settypes
;
755 while (runner
!= NULL
) {
756 if (STREQ(runner
->typename
, typename
))
759 runner
= runner
->next
;
762 return NULL
; /* not found */
765 static struct settype
*settype_load(const char *typename
)
767 char path
[sizeof(IPSET_LIB_DIR
) + sizeof(IPSET_LIB_NAME
) +
769 struct settype
*settype
;
771 /* do some search in list */
772 settype
= settype_find(typename
);
774 return settype
; /* found */
776 /* Else we have to load it */
777 sprintf(path
, IPSET_LIB_DIR IPSET_LIB_NAME
, typename
);
779 if (dlopen(path
, RTLD_NOW
)) {
782 settype
= settype_find(typename
);
788 /* Can't load the settype */
789 exit_error(PARAMETER_PROBLEM
,
790 "Couldn't load settype `%s':%s\n",
791 typename
, dlerror());
793 return NULL
; /* Never executed, but keep compilers happy */
796 static char *check_set_name(char *setname
)
798 if (strlen(setname
) > IP_SET_MAXNAMELEN
- 1)
799 exit_error(PARAMETER_PROBLEM
,
800 "Setname '%s' too long, max %d characters.",
801 setname
, IP_SET_MAXNAMELEN
- 1);
806 static struct settype
*check_set_typename(const char *typename
)
808 if (strlen(typename
) > IP_SET_MAXNAMELEN
- 1)
809 exit_error(PARAMETER_PROBLEM
,
810 "Typename '%s' too long, max %d characters.",
811 typename
, IP_SET_MAXNAMELEN
- 1);
813 return settype_load(typename
);
816 #define MAX(a,b) ((a) > (b) ? (a) : (b))
818 /* Register a new set type */
819 void settype_register(struct settype
*settype
)
824 DP("%s", settype
->typename
);
826 /* Check if this typename already exists */
827 chk
= settype_find(settype
->typename
);
830 exit_error(OTHER_PROBLEM
,
831 "Set type '%s' already registered!\n",
835 if (settype
->protocol_version
!= IP_SET_PROTOCOL_VERSION
)
836 exit_error(OTHER_PROBLEM
,
837 "Set type %s is of wrong protocol version %u!"
838 " I'm of version %u.\n", settype
->typename
,
839 settype
->protocol_version
,
840 IP_SET_PROTOCOL_VERSION
);
842 /* Initialize internal data */
843 settype
->header
= ipset_malloc(settype
->header_size
);
844 size
= MAX(settype
->create_size
, settype
->adt_size
);
845 settype
->data
= ipset_malloc(size
);
848 settype
->next
= all_settypes
;
849 all_settypes
= settype
;
851 DP("%s registered", settype
->typename
);
854 /* Find set functions */
855 struct set
*set_find_byid(ip_set_id_t id
)
857 struct set
*set
= NULL
;
860 for (i
= 0; i
< max_sets
; i
++)
861 if (set_list
[i
] && set_list
[i
]->id
== id
) {
867 exit_error(PARAMETER_PROBLEM
,
868 "Set identified by id %u is not found", id
);
872 struct set
*set_find_byname(const char *name
)
874 struct set
*set
= NULL
;
877 for (i
= 0; i
< max_sets
; i
++)
878 if (set_list
[i
] != NULL
&& STREQ(set_list
[i
]->name
, name
)) {
883 exit_error(PARAMETER_PROBLEM
,
884 "Set %s is not found", name
);
888 static ip_set_id_t
set_find_free_index(const char *name
)
890 ip_set_id_t i
, idx
= IP_SET_INVALID_ID
;
892 for (i
= 0; i
< max_sets
; i
++) {
893 if (idx
== IP_SET_INVALID_ID
894 && set_list
[i
] == NULL
)
896 if (set_list
[i
] != NULL
&& STREQ(set_list
[i
]->name
, name
))
897 exit_error(PARAMETER_PROBLEM
,
898 "Set %s is already defined, cannot be restored",
902 if (idx
== IP_SET_INVALID_ID
)
903 exit_error(PARAMETER_PROBLEM
,
904 "Set %s cannot be restored, "
905 "max number of set %u reached",
912 * Send create set order to kernel
914 static void set_create(const char *name
, struct settype
*settype
)
916 struct ip_set_req_create req_create
;
920 DP("%s %s", name
, settype
->typename
);
922 req_create
.op
= IP_SET_OP_CREATE
;
923 req_create
.version
= protocol_version
;
924 strcpy(req_create
.name
, name
);
925 strcpy(req_create
.typename
, settype
->typename
);
928 settype
->create_final(settype
->data
, settype
->flags
);
930 /* Alloc memory for the data to send */
931 size
= sizeof(struct ip_set_req_create
) + settype
->create_size
;
932 data
= ipset_malloc(size
);
934 /* Add up ip_set_req_create and the settype data */
935 memcpy(data
, &req_create
, sizeof(struct ip_set_req_create
));
936 memcpy(data
+ sizeof(struct ip_set_req_create
),
937 settype
->data
, settype
->create_size
);
939 kernel_sendto(CMD_CREATE
, data
, size
);
943 static void set_restore_create(const char *name
, struct settype
*settype
)
947 DP("%s %s %zu %zu %u %u", name
, settype
->typename
,
948 restore_offset
, sizeof(struct ip_set_restore
),
949 settype
->create_size
, restore_size
);
951 /* Sanity checking */
953 + ALIGNED(sizeof(struct ip_set_restore
))
954 + ALIGNED(settype
->create_size
) > restore_size
)
955 exit_error(PARAMETER_PROBLEM
,
956 "Giving up, restore file is screwed up!");
959 settype
->create_final(settype
->data
, settype
->flags
);
961 /* Fill out restore_data */
962 restore_set
= (struct ip_set_restore
*)
963 (restore_data
+ restore_offset
);
964 strcpy(restore_set
->name
, name
);
965 strcpy(restore_set
->typename
, settype
->typename
);
966 restore_set
->index
= set_find_free_index(name
);
967 restore_set
->header_size
= settype
->create_size
;
968 restore_set
->members_size
= 0;
970 DP("name %s, restore index %u", restore_set
->name
, restore_set
->index
);
971 /* Add settype data */
973 restore_offset
+= ALIGNED(sizeof(struct ip_set_restore
));
974 memcpy(restore_data
+ restore_offset
, settype
->data
, settype
->create_size
);
976 restore_offset
+= ALIGNED(settype
->create_size
);
977 DP("restore_offset: %zu", restore_offset
);
979 /* Add set to set_list */
980 set
= ipset_malloc(sizeof(struct set
));
981 strcpy(set
->name
, name
);
982 set
->settype
= settype
;
983 set
->index
= restore_set
->index
;
984 set_list
[restore_set
->index
] = set
;
988 * Send destroy/flush order to kernel for one or all sets
990 static void set_destroy(const char *name
, unsigned op
, unsigned cmd
)
992 struct ip_set_req_std req
;
994 DP("%s %s", cmd
== CMD_DESTROY
? "destroy" : "flush", name
);
997 req
.version
= protocol_version
;
998 strcpy(req
.name
, name
);
1000 kernel_sendto(cmd
, &req
, sizeof(struct ip_set_req_std
));
1004 * Send rename/swap order to kernel
1006 static void set_rename(const char *name
, const char *newname
,
1007 unsigned op
, unsigned cmd
)
1009 struct ip_set_req_create req
;
1011 DP("%s %s %s", cmd
== CMD_RENAME
? "rename" : "swap",
1015 req
.version
= protocol_version
;
1016 strcpy(req
.name
, name
);
1017 strcpy(req
.typename
, newname
);
1019 kernel_sendto(cmd
, &req
,
1020 sizeof(struct ip_set_req_create
));
1024 * Send MAX_SETS, LIST_SIZE and/or SAVE_SIZE orders to kernel
1026 static size_t load_set_list(const char name
[IP_SET_MAXNAMELEN
],
1028 unsigned op
, unsigned cmd
)
1031 struct ip_set_req_max_sets req_max_sets
;
1032 struct ip_set_name_list
*name_list
;
1035 socklen_t size
, req_size
;
1036 int repeated
= 0, res
= 0;
1038 DP("%s %s", cmd
== CMD_MAX_SETS
? "MAX_SETS"
1039 : cmd
== CMD_LIST_SIZE
? "LIST_SIZE"
1045 for (i
= 0; i
< max_sets
; i
++)
1052 req_max_sets
.op
= IP_SET_OP_MAX_SETS
;
1053 req_max_sets
.version
= protocol_version
;
1054 strcpy(req_max_sets
.set
.name
, name
);
1055 size
= sizeof(req_max_sets
);
1056 kernel_getfrom(CMD_MAX_SETS
, &req_max_sets
, &size
);
1058 DP("got MAX_SETS: sets %d, max_sets %d",
1059 req_max_sets
.sets
, req_max_sets
.max_sets
);
1061 max_sets
= req_max_sets
.max_sets
;
1062 set_list
= ipset_malloc(max_sets
* sizeof(struct set
*));
1063 memset(set_list
, 0, max_sets
* sizeof(struct set
*));
1064 *idx
= req_max_sets
.set
.index
;
1066 if (req_max_sets
.sets
== 0)
1067 /* No sets in kernel */
1071 size
= req_size
= ALIGNED(sizeof(struct ip_set_req_setnames
))
1072 + req_max_sets
.sets
* ALIGNED(sizeof(struct ip_set_name_list
));
1073 data
= ipset_malloc(size
);
1074 ((struct ip_set_req_setnames
*) data
)->op
= op
;
1075 ((struct ip_set_req_setnames
*) data
)->index
= *idx
;
1077 res
= kernel_getfrom_handleerrno(cmd
, data
, &size
);
1079 if (res
!= 0 || size
!= req_size
) {
1081 if (repeated
++ < LIST_TRIES
)
1083 exit_error(OTHER_PROBLEM
,
1084 "Tried to get sets from kernel %d times"
1085 " and failed. Please try again when the load on"
1086 " the sets has gone down.", LIST_TRIES
);
1089 /* Load in setnames */
1090 size
= ALIGNED(sizeof(struct ip_set_req_setnames
));
1091 while (size
+ ALIGNED(sizeof(struct ip_set_name_list
)) <= req_size
) {
1092 name_list
= (struct ip_set_name_list
*)
1094 set
= ipset_malloc(sizeof(struct set
));
1095 strcpy(set
->name
, name_list
->name
);
1096 set
->index
= name_list
->index
;
1097 set
->id
= name_list
->id
;
1098 set
->settype
= settype_load(name_list
->typename
);
1099 set_list
[name_list
->index
] = set
;
1100 DP("loaded %s, type %s, index %u",
1101 set
->name
, set
->settype
->typename
, set
->index
);
1102 size
+= ALIGNED(sizeof(struct ip_set_name_list
));
1104 /* Size to get set members */
1105 size
= ((struct ip_set_req_setnames
*)data
)->size
;
1114 static size_t save_set(void *data
, size_t offset
, size_t len
)
1116 struct ip_set_save
*set_save
=
1117 (struct ip_set_save
*) (data
+ offset
);
1119 struct settype
*settype
;
1122 DP("offset %zu (%zu/%u/%u), len %zu", offset
,
1123 sizeof(struct ip_set_save
),
1124 set_save
->header_size
, set_save
->members_size
,
1126 if (offset
+ ALIGNED(sizeof(struct ip_set_save
)) > len
1127 || offset
+ ALIGNED(sizeof(struct ip_set_save
))
1128 + set_save
->header_size
+ set_save
->members_size
> len
)
1129 exit_error(OTHER_PROBLEM
,
1130 "Save operation failed, try again later.");
1132 DP("index: %u", set_save
->index
);
1133 if (set_save
->index
== IP_SET_INVALID_ID
) {
1135 return ALIGNED(sizeof(struct ip_set_save
));
1137 set
= set_list
[set_save
->index
];
1139 exit_error(OTHER_PROBLEM
,
1140 "Save set failed, try again later.");
1141 settype
= set
->settype
;
1143 /* Init set header */
1144 used
= ALIGNED(sizeof(struct ip_set_save
));
1145 settype
->initheader(set
, data
+ offset
+ used
);
1147 /* Print create set */
1148 settype
->saveheader(set
, OPT_NUMERIC
);
1151 used
+= set_save
->header_size
;
1152 settype
->saveips(set
, data
+ offset
+ used
,
1153 set_save
->members_size
, OPT_NUMERIC
,
1156 return (used
+ set_save
->members_size
);
1159 static int try_save_sets(const char name
[IP_SET_MAXNAMELEN
])
1162 socklen_t size
, req_size
= 0;
1165 time_t now
= time(NULL
);
1167 /* Load set_list from kernel */
1168 size
= load_set_list(name
, &idx
,
1169 IP_SET_OP_SAVE_SIZE
, CMD_SAVE
);
1172 /* Get sets and print them */
1173 /* Take into account marker */
1174 req_size
= (size
+= ALIGNED(sizeof(struct ip_set_save
)));
1175 data
= ipset_malloc(size
);
1176 ((struct ip_set_req_list
*) data
)->op
= IP_SET_OP_SAVE
;
1177 ((struct ip_set_req_list
*) data
)->index
= idx
;
1178 res
= kernel_getfrom_handleerrno(CMD_SAVE
, data
, &size
);
1180 if (res
!= 0 || size
!= req_size
) {
1181 DP("Try again: res: %i, size %u, req_size: %u",
1182 res
, size
, req_size
);
1188 printf("# Generated by ipset %s on %s", IPSET_VERSION
, ctime(&now
));
1190 while (size
< req_size
) {
1191 DP("size: %u, req_size: %u", size
, req_size
);
1192 size
+= save_set(data
, size
, req_size
);
1196 printf("# Completed on %s", ctime(&now
));
1202 * Performs a save to stdout
1204 static void set_save(const char name
[IP_SET_MAXNAMELEN
])
1209 for (i
= 0; i
< LIST_TRIES
; i
++)
1210 if (try_save_sets(name
) == 0)
1213 if (errno
== EAGAIN
)
1214 exit_error(OTHER_PROBLEM
,
1215 "Tried to save sets from kernel %d times"
1216 " and failed. Please try again when the load on"
1217 " the sets has gone down.", LIST_TRIES
);
1219 kernel_error(CMD_SAVE
, errno
);
1226 /* global new argv and argc */
1227 static char *newargv
[255];
1228 static int newargc
= 0;
1230 /* Build faked argv from parsed line */
1231 static void build_argv(unsigned line
, char *buffer
) {
1236 for (i
= 1; i
< newargc
; i
++)
1240 ptr
= strtok(buffer
, " \t\n");
1241 newargv
[newargc
++] = ipset_strdup(ptr
);
1242 while ((ptr
= strtok(NULL
, " \t\n")) != NULL
) {
1243 if ((newargc
+ 1) < (int)(sizeof(newargv
)/sizeof(char *)))
1244 newargv
[newargc
++] = ipset_strdup(ptr
);
1246 exit_error(PARAMETER_PROBLEM
,
1247 "Line %d is too long to restore\n", line
);
1251 static FILE *create_tempfile(void)
1253 char buffer
[1024], __tmpdir
[] = "/tmp";
1254 char *tmpdir
= NULL
;
1259 if (!(tmpdir
= getenv("TMPDIR")) && !(tmpdir
= getenv("TMP")))
1261 filename
= ipset_malloc(strlen(tmpdir
) + strlen(TEMPFILE_PATTERN
) + 1);
1262 strcpy(filename
, tmpdir
);
1263 strcat(filename
, TEMPFILE_PATTERN
);
1265 (void) umask(077); /* Create with restrictive permissions */
1266 fd
= mkstemp(filename
);
1268 exit_error(OTHER_PROBLEM
, "Could not create temporary file.");
1269 if (!(file
= fdopen(fd
, "r+")))
1270 exit_error(OTHER_PROBLEM
, "Could not open temporary file.");
1271 if (unlink(filename
) == -1)
1272 exit_error(OTHER_PROBLEM
, "Could not unlink temporary file.");
1275 while (fgets(buffer
, sizeof(buffer
), stdin
)) {
1276 fputs(buffer
, file
);
1278 fseek(file
, 0L, SEEK_SET
);
1284 * Performs a restore from a file
1286 static void set_restore(char *argv0
)
1289 char *ptr
, *name
= NULL
;
1292 struct settype
*settype
= NULL
;
1293 struct ip_set_req_setnames
*header
;
1298 /* Create and store stdin in temporary file */
1299 in
= create_tempfile();
1301 /* Load existing sets from kernel */
1302 load_set_list(IPSET_TOKEN_ALL
, &idx
,
1303 IP_SET_OP_LIST_SIZE
, CMD_RESTORE
);
1306 restore_size
= ALIGNED(sizeof(struct ip_set_req_setnames
)); /* header */
1307 DP("restore_size: %u", restore_size
);
1308 /* First pass: calculate required amount of data */
1309 while (fgets(buffer
, sizeof(buffer
), in
)) {
1312 if (buffer
[0] == '\n')
1314 else if (buffer
[0] == '#')
1316 else if (strcmp(buffer
, "COMMIT\n") == 0) {
1317 /* Enable restore mode */
1323 ptr
= strtok(buffer
, " \t\n");
1330 || ptr
[2] != '\0') {
1331 exit_error(PARAMETER_PROBLEM
,
1332 "Line %u does not start as a valid restore command\n",
1337 ptr
= strtok(NULL
, " \t\n");
1338 DP("setname: %s", ptr
);
1340 exit_error(PARAMETER_PROBLEM
,
1341 "Missing set name in line %u\n",
1346 name
= check_set_name(ptr
);
1348 ptr
= strtok(NULL
, " \t\n");
1350 exit_error(PARAMETER_PROBLEM
,
1351 "Missing settype in line %u\n",
1353 settype
= check_set_typename(ptr
);
1354 restore_size
+= ALIGNED(sizeof(struct ip_set_restore
))
1355 + ALIGNED(settype
->create_size
);
1356 DP("restore_size (N): %u", restore_size
);
1361 || strncmp(name
, ptr
, sizeof(name
)) != 0)
1362 exit_error(PARAMETER_PROBLEM
,
1363 "Add IP to set %s in line %u without "
1364 "preceding corresponding create set line\n",
1366 restore_size
+= ALIGNED(settype
->adt_size
);
1367 DP("restore_size (A): %u", restore_size
);
1371 exit_error(PARAMETER_PROBLEM
,
1372 "Unrecognized restore command in line %u\n",
1375 } /* end of switch */
1377 /* Sanity checking */
1379 exit_error(PARAMETER_PROBLEM
,
1380 "Missing COMMIT line\n");
1381 restore_size
+= ALIGNED(sizeof(struct ip_set_restore
)); /* marker */
1382 DP("restore_size: %u", restore_size
);
1383 restore_data
= ipset_malloc(restore_size
);
1384 header
= (struct ip_set_req_setnames
*) restore_data
;
1385 header
->op
= IP_SET_OP_RESTORE
;
1386 header
->size
= restore_size
;
1387 restore_offset
= ALIGNED(sizeof(struct ip_set_req_setnames
));
1389 /* Rewind to scan the file again */
1390 fseek(in
, 0L, SEEK_SET
);
1391 first_pass
= restore_line
;
1394 /* Initialize newargv/newargc */
1395 newargv
[newargc
++] = ipset_strdup(argv0
);
1397 /* Second pass: build up restore request */
1398 while (fgets(buffer
, sizeof(buffer
), in
)) {
1401 if (buffer
[0] == '\n')
1403 else if (buffer
[0] == '#')
1405 else if (strcmp(buffer
, "COMMIT\n") == 0)
1407 DP("restoring: %s", buffer
);
1408 /* Build faked argv, argc */
1409 build_argv(restore_line
, buffer
);
1410 for (i
= 0; i
< newargc
; i
++)
1411 DP("argv[%u]: %s", i
, newargv
[i
]);
1414 parse_commandline(newargc
, newargv
);
1416 exit_error(PARAMETER_PROBLEM
,
1417 "Broken restore file\n");
1419 if (restore_size
== (restore_offset
+ ALIGNED(sizeof(struct ip_set_restore
)))) {
1421 struct ip_set_restore
*marker
=
1422 (struct ip_set_restore
*) (restore_data
+ restore_offset
);
1424 marker
->index
= IP_SET_INVALID_ID
;
1425 marker
->header_size
= marker
->members_size
= 0;
1426 restore_offset
+= ALIGNED(sizeof(struct ip_set_restore
));
1427 DP("restore marker, restore_offset: %zu", restore_offset
);
1429 if (restore_size
!= restore_offset
)
1430 exit_error(PARAMETER_PROBLEM
,
1431 "Giving up, restore file is screwed up!");
1432 res
= kernel_getfrom_handleerrno(CMD_RESTORE
, restore_data
, &restore_size
);
1435 if (restore_size
!= sizeof(struct ip_set_req_setnames
))
1436 exit_error(PARAMETER_PROBLEM
,
1437 "Communication with kernel failed (%u %u)!",
1438 restore_size
, sizeof(struct ip_set_req_setnames
));
1440 header
= (struct ip_set_req_setnames
*) restore_data
;
1441 if (header
->size
!= 0)
1442 exit_error(PARAMETER_PROBLEM
,
1443 "Committing restoring failed at line %u!",
1449 * Send ADT_GET order to kernel for a set
1451 static struct set
*set_adt_get(const char *name
)
1453 struct ip_set_req_adt_get req_adt_get
;
1459 check_protocolversion();
1461 req_adt_get
.op
= IP_SET_OP_ADT_GET
;
1462 req_adt_get
.version
= protocol_version
;
1463 strcpy(req_adt_get
.set
.name
, name
);
1464 size
= sizeof(struct ip_set_req_adt_get
);
1466 kernel_getfrom(CMD_ADT_GET
, (void *) &req_adt_get
, &size
);
1468 set
= ipset_malloc(sizeof(struct set
));
1469 strcpy(set
->name
, name
);
1470 set
->index
= req_adt_get
.set
.index
;
1471 set
->settype
= settype_load(req_adt_get
.typename
);
1477 * Send add/del/test order to kernel for a set
1479 static int set_adtip(struct set
*set
, const char *adt
,
1480 unsigned op
, unsigned cmd
)
1482 struct ip_set_req_adt
*req_adt
;
1487 DP("%s -> %s", set
->name
, adt
);
1489 /* Alloc memory for the data to send */
1490 size
= ALIGNED(sizeof(struct ip_set_req_adt
)) + set
->settype
->adt_size
;
1491 DP("alloc size %zu", size
);
1492 data
= ipset_malloc(size
);
1494 /* Fill out the request */
1495 req_adt
= (struct ip_set_req_adt
*) data
;
1497 req_adt
->index
= set
->index
;
1498 memcpy(data
+ ALIGNED(sizeof(struct ip_set_req_adt
)),
1499 set
->settype
->data
, set
->settype
->adt_size
);
1501 if (kernel_sendto_handleerrno(cmd
, data
, size
) == -1)
1503 case IP_SET_OP_ADD_IP
:
1504 exit_error(OTHER_PROBLEM
, "%s is already in set %s.",
1507 case IP_SET_OP_DEL_IP
:
1508 exit_error(OTHER_PROBLEM
, "%s is not in set %s.",
1511 case IP_SET_OP_TEST_IP
:
1512 ipset_printf("%s is in set %s.", adt
, set
->name
);
1520 case IP_SET_OP_TEST_IP
:
1521 ipset_printf("%s is NOT in set %s.", adt
, set
->name
);
1532 static void set_restore_add(struct set
*set
, const char *adt UNUSED
)
1534 DP("%s %s", set
->name
, adt
);
1535 /* Sanity checking */
1536 if (restore_offset
+ ALIGNED(set
->settype
->adt_size
) > restore_size
)
1537 exit_error(PARAMETER_PROBLEM
,
1538 "Giving up, restore file is screwed up!");
1540 memcpy(restore_data
+ restore_offset
,
1541 set
->settype
->data
, set
->settype
->adt_size
);
1542 restore_set
->members_size
+= ALIGNED(set
->settype
->adt_size
);
1543 restore_offset
+= ALIGNED(set
->settype
->adt_size
);
1545 DP("restore_offset: %zu", restore_offset
);
1552 /* Help function to set_list() */
1553 static size_t print_set(void *data
, unsigned options
)
1555 struct ip_set_list
*setlist
= data
;
1556 struct set
*set
= set_list
[setlist
->index
];
1557 struct settype
*settype
= set
->settype
;
1560 /* Pretty print the set */
1561 DP("header size: %u, members size: %u",
1562 setlist
->header_size
, setlist
->members_size
);
1563 printf("Name: %s\n", set
->name
);
1564 printf("Type: %s\n", settype
->typename
);
1565 printf("References: %d\n", setlist
->ref
);
1568 offset
= ALIGNED(sizeof(struct ip_set_list
));
1569 settype
->initheader(set
, data
+ offset
);
1571 /* Pretty print the type header */
1573 settype
->printheader(set
, options
);
1575 /* Pretty print all IPs */
1576 printf("Members:\n");
1577 offset
+= setlist
->header_size
;
1578 DP("Aligned: %u, offset: %zu, members_size %u\n", !DONT_ALIGN
, offset
,
1579 setlist
->members_size
);
1580 if (options
& OPT_SORTED
)
1581 settype
->printips_sorted(set
, data
+ offset
,
1582 setlist
->members_size
, options
,
1585 settype
->printips(set
, data
+ offset
,
1586 setlist
->members_size
, options
,
1589 printf("\n"); /* One newline between sets */
1591 return (offset
+ setlist
->members_size
);
1594 static int try_list_sets(const char name
[IP_SET_MAXNAMELEN
],
1599 socklen_t size
, req_size
;
1602 /* Default is numeric listing */
1603 if (!(options
& (OPT_RESOLVE
|OPT_NUMERIC
)))
1604 options
|= OPT_NUMERIC
;
1607 /* Load set_list from kernel */
1608 size
= req_size
= load_set_list(name
, &idx
,
1609 IP_SET_OP_LIST_SIZE
, CMD_LIST
);
1612 /* Get sets and print them */
1613 data
= ipset_malloc(size
);
1614 ((struct ip_set_req_list
*) data
)->op
= IP_SET_OP_LIST
;
1615 ((struct ip_set_req_list
*) data
)->index
= idx
;
1616 res
= kernel_getfrom_handleerrno(CMD_LIST
, data
, &size
);
1617 DP("get_lists getsockopt() res=%d errno=%d", res
, errno
);
1619 if (res
!= 0 || size
!= req_size
) {
1625 while (size
!= req_size
)
1626 size
+= print_set(data
+ size
, options
);
1632 /* Print a set or all sets
1633 * All sets: name = NULL
1635 static void list_sets(const char name
[IP_SET_MAXNAMELEN
], unsigned options
)
1640 for (i
= 0; i
< LIST_TRIES
; i
++)
1641 if (try_list_sets(name
, options
) == 0)
1644 if (errno
== EAGAIN
)
1645 exit_error(OTHER_PROBLEM
,
1646 "Tried to list sets from kernel %d times"
1647 " and failed. Please try again when the load on"
1648 " the sets has gone down.", LIST_TRIES
);
1650 kernel_error(CMD_LIST
, errno
);
1654 * If settype is non null help for that type is printed as well
1656 static void set_help(const struct settype
*settype
)
1659 "Usage: %s -N new-set settype [options]\n"
1660 " %s -[XFLSH] [set] [options]\n"
1661 " %s -[EW] from-set to-set\n"
1662 " %s -[ADT] set IP\n"
1665 " %s -h (print this help information)\n\n",
1666 program_name
, program_version
,
1667 program_name
, program_name
, program_name
,
1668 program_name
, program_name
, program_name
,
1671 printf("Commands:\n"
1672 "Either long or short options are allowed.\n"
1673 " --create -N setname settype <options>\n"
1674 " Create a new set\n"
1675 " --destroy -X [setname]\n"
1676 " Destroy a set or all sets\n"
1677 " --flush -F [setname]\n"
1678 " Flush a set or all sets\n"
1679 " --rename -E from-set to-set\n"
1680 " Rename from-set to to-set\n"
1681 " --swap -W from-set to-set\n"
1682 " Swap the content of two existing sets\n"
1683 " --list -L [setname] [options]\n"
1684 " List the IPs in a set or all sets\n"
1685 " --save -S [setname]\n"
1686 " Save the set or all sets to stdout\n"
1687 " --restore -R [option]\n"
1688 " Restores a saved state\n"
1689 " --add -A setname IP\n"
1690 " Add an IP to a set\n"
1691 " --del -D setname IP\n"
1692 " Deletes an IP from a set\n"
1693 " --test -T setname IP \n"
1694 " Tests if an IP exists in a set.\n"
1695 " --help -H [settype]\n"
1696 " Prints this help, and settype specific help\n"
1698 " Prints version information\n\n"
1700 " --sorted -s Numeric sort of the IPs in -L\n"
1701 " --numeric -n Numeric output of addresses in a -L (default)\n"
1702 " --resolve -r Try to resolve addresses in a -L\n"
1703 " --quiet -q Suppress any output to stdout and stderr.\n");
1705 printf(" --debug -z Enable debugging\n\n");
1710 if (settype
!= NULL
) {
1711 printf("Type '%s' specific:\n", settype
->typename
);
1716 static int find_cmd(int option
)
1720 for (i
= 1; i
<= NUMBER_OF_CMD
; i
++)
1721 if (cmdflags
[i
] == option
)
1727 static int parse_adt_cmdline(int command
,
1731 struct settype
**settype
)
1735 *set
= restore
? set_find_byname(name
) : set_adt_get(name
);
1737 /* Reset space for adt data */
1738 *settype
= (*set
)->settype
;
1739 memset((*settype
)->data
, 0, (*settype
)->adt_size
);
1741 res
= (*settype
)->adt_parser(command
, adt
, (*settype
)->data
);
1746 /* Main worker function */
1747 int parse_commandline(int argc
, char *argv
[])
1750 int command
= CMD_NONE
;
1751 unsigned options
= 0;
1754 char *name
= NULL
; /* All except -H, -R */
1755 char *newname
= NULL
; /* -E, -W */
1756 char *adt
= NULL
; /* -A, -D, -T */
1757 struct set
*set
= NULL
; /* -A, -D, -T */
1758 struct settype
*settype
= NULL
; /* -N, -H */
1759 char all_sets
[] = IPSET_TOKEN_ALL
;
1761 struct option
*opts
= opts_long
;
1763 /* Suppress error messages: we may add new options if we
1764 demand-load a protocol. */
1766 /* Reset optind to 0 for restore */
1769 while ((c
= getopt_long(argc
, argv
, opts_short
, opts
, NULL
)) != -1) {
1771 DP("commandline parsed: opt %c (%s)", c
, argv
[optind
]);
1778 case 'H':{ /* Help: -H [typename [options]] */
1779 check_protocolversion();
1780 set_command(&command
, CMD_HELP
);
1783 settype
= check_set_typename(optarg
);
1784 else if (optind
< argc
1785 && argv
[optind
][0] != '-')
1786 settype
= check_set_typename(argv
[optind
++]);
1792 case 'v': { /* Version */
1793 printf("%s v%s, protocol version %u.\n",
1794 program_name
, program_version
,
1795 IP_SET_PROTOCOL_VERSION
);
1796 check_protocolversion();
1797 printf("Kernel module protocol version %u.\n",
1802 case 'N':{ /* Create: -N name typename options */
1803 set_command(&command
, CMD_CREATE
);
1805 name
= check_set_name(optarg
);
1807 /* Protect reserved names */
1809 exit_error(PARAMETER_PROBLEM
,
1810 "setname might not start with colon",
1811 cmd2char(CMD_CREATE
));
1814 && argv
[optind
][0] != '-')
1815 settype
= check_set_typename(argv
[optind
++]);
1817 exit_error(PARAMETER_PROBLEM
,
1818 "-%c requires setname and settype",
1819 cmd2char(CMD_CREATE
));
1821 DP("merge options");
1822 /* Merge the create options */
1823 opts
= merge_options(opts
,
1824 settype
->create_opts
,
1825 &settype
->option_offset
);
1827 /* Reset space for create data */
1828 memset(settype
->data
, 0, settype
->create_size
);
1830 /* Zero the flags */
1833 DP("call create_init");
1834 /* Call the settype create_init */
1835 settype
->create_init(settype
->data
);
1840 case 'X': /* Destroy */
1841 case 'F': /* Flush */
1842 case 'L': /* List */
1843 case 'S':{ /* Save */
1844 set_command(&command
, find_cmd(c
));
1847 name
= check_set_name(optarg
);
1848 else if (optind
< argc
1849 && argv
[optind
][0] != '-')
1850 name
= check_set_name(argv
[optind
++]);
1857 case 'R':{ /* Restore */
1858 set_command(&command
, find_cmd(c
));
1863 case 'E': /* Rename */
1864 case 'W':{ /* Swap */
1865 set_command(&command
, find_cmd(c
));
1866 name
= check_set_name(optarg
);
1869 && argv
[optind
][0] != '-')
1870 newname
= check_set_name(argv
[optind
++]);
1872 exit_error(PARAMETER_PROBLEM
,
1873 "-%c requires a setname "
1874 "and the new name for that set",
1875 cmd2char(CMD_RENAME
));
1880 case 'A': /* Add IP */
1881 case 'D': /* Del IP */
1882 case 'T':{ /* Test IP */
1883 set_command(&command
, find_cmd(c
));
1885 name
= check_set_name(optarg
);
1889 && argv
[optind
][0] != '-')
1890 adt
= argv
[optind
++];
1892 exit_error(PARAMETER_PROBLEM
,
1893 "-%c requires setname and IP",
1896 res
= parse_adt_cmdline(command
, name
, adt
,
1900 exit_error(PARAMETER_PROBLEM
,
1911 add_option(&options
, OPT_NUMERIC
);
1915 if (!(options
& OPT_NUMERIC
))
1916 add_option(&options
, OPT_RESOLVE
);
1920 add_option(&options
, OPT_SORTED
);
1924 add_option(&options
, OPT_QUIET
);
1929 case 'z': /* debug */
1930 add_option(&options
, OPT_DEBUG
);
1935 case 1: /* non option */
1936 printf("Bad argument `%s'\n", optarg
);
1937 exit_tryhelp(PARAMETER_PROBLEM
);
1938 break; /*always good */
1945 res
= settype
->create_parse(
1946 c
- settype
->option_offset
,
1953 res
= 0; /* failed */
1954 } /* switch (command) */
1958 exit_error(PARAMETER_PROBLEM
,
1968 } /* while( getopt_long() ) */
1972 exit_error(PARAMETER_PROBLEM
,
1973 "unknown arguments found on commandline");
1974 if (command
== CMD_NONE
)
1975 exit_error(PARAMETER_PROBLEM
, "no command specified");
1978 generic_opt_check(command
, options
);
1980 DP("cmd: %c", cmd2char(command
));
1982 check_protocolversion();
1988 set_restore_create(name
, settype
);
1990 set_create(name
, settype
);
1994 set_destroy(name
, IP_SET_OP_DESTROY
, CMD_DESTROY
);
1998 set_destroy(name
, IP_SET_OP_FLUSH
, CMD_FLUSH
);
2002 set_rename(name
, newname
, IP_SET_OP_RENAME
, CMD_RENAME
);
2006 set_rename(name
, newname
, IP_SET_OP_SWAP
, CMD_SWAP
);
2010 list_sets(name
, options
);
2018 set_restore(argv
[0]);
2023 set_restore_add(set
, adt
);
2025 set_adtip(set
, adt
, IP_SET_OP_ADD_IP
, CMD_ADD
);
2029 set_adtip(set
, adt
, IP_SET_OP_DEL_IP
, CMD_DEL
);
2033 res
= set_adtip(set
, adt
, IP_SET_OP_TEST_IP
, CMD_TEST
);
2041 /* Will never happen */
2042 break; /* Keep the compiler happy */
2044 } /* switch( command ) */
2050 int main(int argc
, char *argv
[])
2052 return parse_commandline(argc
, argv
);