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.
17 #include <sys/socket.h>
18 #include <sys/types.h>
20 #include <arpa/inet.h>
24 #ifndef __always_inline
25 #define __always_inline inline
27 #include <asm/bitops.h>
31 char program_name[] = "ipset";
32 char program_version[] = IPSET_VERSION;
34 /* The list of loaded set types */
35 static struct settype *all_settypes = NULL;
38 struct set **set_list = NULL;
39 ip_set_id_t max_sets = 0;
41 /* Suppress output to stdout and stderr? */
42 static int option_quiet = 0;
44 /* Data for restore mode */
45 static int restore = 0;
46 void *restore_data = NULL;
47 struct ip_set_restore *restore_set = NULL;
48 size_t restore_offset = 0, restore_size;
51 #define TEMPFILE_PATTERN "/ipsetXXXXXX"
57 #define OPTION_OFFSET 256
58 static unsigned int global_option_offset = 0;
60 /* Most of these command parsing functions are borrowed from iptables.c */
62 static const char cmdflags[] = { ' ', /* CMD_NONE */
63 'N', 'X', 'F', 'E', 'W', 'L', 'S', 'R',
64 'A', 'D', 'T', 'B', 'U', 'H', 'V',
68 #define OPT_NONE 0x0000U
69 #define OPT_NUMERIC 0x0001U /* -n */
70 #define OPT_SORTED 0x0002U /* -s */
71 #define OPT_QUIET 0x0004U /* -q */
72 #define OPT_DEBUG 0x0008U /* -z */
73 #define OPT_BINDING 0x0010U /* -b */
74 #define NUMBER_OF_OPT 5
75 static const char optflags[] =
76 { 'n', 's', 'q', 'z', 'b' };
78 static struct option opts_long[] = {
80 {"create", 1, 0, 'N'},
81 {"destroy", 2, 0, 'X'},
83 {"rename", 1, 0, 'E'},
88 {"restore", 0, 0, 'R'},
90 /* ip in set operations */
95 /* binding operations */
97 {"unbind", 1, 0, 'U'},
100 {"numeric", 0, 0, 'n'},
101 {"sorted", 0, 0, 's'},
102 {"quiet", 0, 0, 'q'},
103 {"binding", 1, 0, 'b'},
106 /* debug (if compiled with it) */
107 {"debug", 0, 0, 'z'},
110 /* version and help */
111 {"version", 0, 0, 'V'},
118 static char opts_short[] =
119 "-N:X::F::E:W:L::S::RA:D:T:B:U:nsqzb:Vh::H::";
121 /* Table of legal combinations of commands and options. If any of the
122 * given commands make an option legal, that option is legal.
129 static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] = {
131 /*CREATE*/ {'x', 'x', ' ', ' ', 'x'},
132 /*DESTROY*/ {'x', 'x', ' ', ' ', 'x'},
133 /*FLUSH*/ {'x', 'x', ' ', ' ', 'x'},
134 /*RENAME*/ {'x', 'x', ' ', ' ', 'x'},
135 /*SWAP*/ {'x', 'x', ' ', ' ', 'x'},
136 /*LIST*/ {' ', ' ', 'x', ' ', 'x'},
137 /*SAVE*/ {'x', 'x', ' ', ' ', 'x'},
138 /*RESTORE*/ {'x', 'x', ' ', ' ', 'x'},
139 /*ADD*/ {'x', 'x', ' ', ' ', 'x'},
140 /*DEL*/ {'x', 'x', ' ', ' ', 'x'},
141 /*TEST*/ {'x', 'x', ' ', ' ', ' '},
142 /*BIND*/ {'x', 'x', ' ', ' ', '+'},
143 /*UNBIND*/ {'x', 'x', ' ', ' ', 'x'},
144 /*HELP*/ {'x', 'x', 'x', ' ', 'x'},
145 /*VERSION*/ {'x', 'x', 'x', ' ', 'x'},
148 /* Main parser function */
149 int parse_commandline(int argc, char *argv[]);
151 void exit_tryhelp(int status)
154 "Try `%s -H' or '%s --help' for more information.\n",
155 program_name, program_name);
159 void exit_error(enum exittype status, char *msg, ...)
165 fprintf(stderr, "%s v%s: ", program_name, program_version);
166 vfprintf(stderr, msg, args);
168 fprintf(stderr, "\n");
170 fprintf(stderr, "Restore failed at line %u:\n", line);
171 if (status == PARAMETER_PROBLEM)
172 exit_tryhelp(status);
173 if (status == VERSION_PROBLEM)
175 "Perhaps %s or your kernel needs to be upgraded.\n",
182 void ipset_printf(char *msg, ...)
188 vfprintf(stdout, msg, args);
190 fprintf(stdout, "\n");
194 static void generic_opt_check(int command, int options)
198 /* Check that commands are valid with options. Complicated by the
199 * fact that if an option is legal with *any* command given, it is
200 * legal overall (ie. -z and -l).
202 for (i = 0; i < NUMBER_OF_OPT; i++) {
203 legal = 0; /* -1 => illegal, 1 => legal, 0 => undecided. */
205 for (j = 1; j <= NUMBER_OF_CMD; j++) {
209 if (!(options & (1 << i))) {
210 if (commands_v_options[j-1][i] == '+')
211 exit_error(PARAMETER_PROBLEM,
212 "You need to supply the `-%c' "
213 "option for this command\n",
216 if (commands_v_options[j-1][i] != 'x')
223 exit_error(PARAMETER_PROBLEM,
224 "Illegal option `-%c' with this command\n",
229 static char opt2char(int option)
232 for (ptr = optflags; option > 1; option >>= 1, ptr++);
237 static char cmd2char(int option)
239 if (option <= CMD_NONE || option > NUMBER_OF_CMD)
242 return cmdflags[option];
245 static int kernel_getsocket(void)
249 sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
251 exit_error(OTHER_PROBLEM,
252 "You need to be root to perform this command.");
257 static void kernel_error(unsigned cmd, int err)
260 struct translate_error {
265 { /* Generic error codes */
266 { EPERM, 0, "Missing capability" },
267 { EBADF, 0, "Invalid socket option" },
268 { EINVAL, 0, "Size mismatch for expected socket data" },
269 { ENOMEM, 0, "Not enough memory" },
270 { EFAULT, 0, "Failed to copy data" },
271 { EPROTO, 0, "ipset kernel/userspace version mismatch" },
272 { EBADMSG, 0, "Unknown command" },
273 /* Per command error codes */
274 /* Reserved ones for add/del/test to handle internally:
277 { ENOENT, CMD_CREATE, "Unknown set type" },
278 { ENOENT, 0, "Unknown set" },
279 { EAGAIN, 0, "Sets are busy, try again later" },
280 { ERANGE, CMD_CREATE, "No free slot remained to add a new set" },
281 { ERANGE, 0, "IP/port is outside of the set" },
282 { ENOEXEC, CMD_CREATE, "Invalid parameters to create a set" },
283 { ENOEXEC, CMD_SWAP, "Sets with different types cannot be swapped" },
284 { EEXIST, CMD_CREATE, "Set already exists" },
285 { EEXIST, CMD_RENAME, "Set with new name already exists" },
286 { EBUSY, 0, "Set is in use, operation not permitted" },
288 for (i = 0; i < sizeof(table)/sizeof(struct translate_error); i++) {
289 if ((table[i].cmd == cmd || table[i].cmd == 0)
290 && table[i].err == err)
291 exit_error(err == EPROTO ? VERSION_PROBLEM
295 exit_error(OTHER_PROBLEM, "Error from kernel: %s", strerror(err));
298 static void kernel_getfrom(unsigned cmd, void *data, size_t * size)
301 int sockfd = kernel_getsocket();
304 res = getsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
306 DP("res=%d errno=%d", res, errno);
309 kernel_error(cmd, errno);
312 static int kernel_sendto_handleerrno(unsigned cmd, unsigned op,
313 void *data, size_t size)
316 int sockfd = kernel_getsocket();
319 res = setsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
321 DP("res=%d errno=%d", res, errno);
327 kernel_error(cmd, errno);
330 return 0; /* all ok */
333 static void kernel_sendto(unsigned cmd, void *data, size_t size)
336 int sockfd = kernel_getsocket();
339 res = setsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
341 DP("res=%d errno=%d", res, errno);
344 kernel_error(cmd, errno);
347 static int kernel_getfrom_handleerrno(unsigned cmd, void *data, size_t * size)
350 int sockfd = kernel_getsocket();
353 res = getsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
355 DP("res=%d errno=%d", res, errno);
361 kernel_error(cmd, errno);
364 return 0; /* all ok */
367 static void check_protocolversion(void)
369 struct ip_set_req_version req_version;
370 size_t size = sizeof(struct ip_set_req_version);
371 int sockfd = kernel_getsocket();
374 req_version.op = IP_SET_OP_VERSION;
375 res = getsockopt(sockfd, SOL_IP, SO_IP_SET, &req_version, &size);
378 ipset_printf("I'm of protocol version %u.\n"
379 "Kernel module is not loaded in, "
380 "cannot verify kernel version.",
381 IP_SET_PROTOCOL_VERSION);
384 if (req_version.version != IP_SET_PROTOCOL_VERSION)
385 exit_error(OTHER_PROBLEM,
386 "Kernel ipset code is of protocol version %u."
387 "I'm of protocol version %u.\n"
388 "Please upgrade your kernel and/or ipset(8) utillity.",
389 req_version.version, IP_SET_PROTOCOL_VERSION);
392 static void set_command(int *cmd, const int newcmd)
394 if (*cmd != CMD_NONE)
395 exit_error(PARAMETER_PROBLEM, "Can't use -%c with -%c\n",
396 cmd2char(*cmd), cmd2char(newcmd));
400 static void add_option(unsigned int *options, unsigned int option)
402 if (*options & option)
403 exit_error(PARAMETER_PROBLEM,
404 "multiple -%c flags not allowed",
409 void *ipset_malloc(size_t size)
416 if ((p = malloc(size)) == NULL) {
417 perror("ipset: not enough memory");
423 char *ipset_strdup(const char *s)
427 if ((p = strdup(s)) == NULL) {
428 perror("ipset: not enough memory");
434 void ipset_free(void **data)
443 static struct option *merge_options(struct option *oldopts,
444 const struct option *newopts,
445 unsigned int *option_offset)
447 unsigned int num_old, num_new, i;
448 struct option *merge;
450 for (num_old = 0; oldopts[num_old].name; num_old++);
451 for (num_new = 0; newopts[num_new].name; num_new++);
453 global_option_offset += OPTION_OFFSET;
454 *option_offset = global_option_offset;
456 merge = ipset_malloc(sizeof(struct option) * (num_new + num_old + 1));
457 memcpy(merge, oldopts, num_old * sizeof(struct option));
458 for (i = 0; i < num_new; i++) {
459 merge[num_old + i] = newopts[i];
460 merge[num_old + i].val += *option_offset;
462 memset(merge + num_old + num_new, 0, sizeof(struct option));
467 static char *ip_tohost(const struct in_addr *addr)
469 struct hostent *host;
471 if ((host = gethostbyaddr((char *) addr,
472 sizeof(struct in_addr),
474 DP("%s", host->h_name);
475 return (char *) host->h_name;
478 return (char *) NULL;
481 static char *ip_tonetwork(const struct in_addr *addr)
485 if ((net = getnetbyaddr((long) ntohl(addr->s_addr),
487 DP("%s", net->n_name);
488 return (char *) net->n_name;
491 return (char *) NULL;
494 /* Return a string representation of an IP address.
495 * Please notice that a pointer to static char* area is returned.
497 char *ip_tostring(ip_set_ip_t ip, unsigned options)
500 addr.s_addr = htonl(ip);
502 if (!(options & OPT_NUMERIC)) {
504 if ((name = ip_tohost(&addr)) != NULL ||
505 (name = ip_tonetwork(&addr)) != NULL)
509 return inet_ntoa(addr);
512 char *binding_ip_tostring(struct set *set, ip_set_ip_t ip, unsigned options)
514 return ip_tostring(ip, options);
516 char *ip_tostring_numeric(ip_set_ip_t ip)
518 return ip_tostring(ip, OPT_NUMERIC);
521 /* Fills the 'ip' with the parsed ip or host in host byte order */
522 void parse_ip(const char *str, ip_set_ip_t * ip)
524 struct hostent *host;
529 if (inet_aton(str, &addr) != 0) {
530 *ip = ntohl(addr.s_addr); /* We want host byte order */
534 host = gethostbyname(str);
536 if (host->h_addrtype != AF_INET ||
537 host->h_length != sizeof(struct in_addr))
538 exit_error(PARAMETER_PROBLEM,
539 "host/network `%s' not an internet name",
541 if (host->h_addr_list[1] != 0)
542 exit_error(PARAMETER_PROBLEM,
543 "host/network `%s' resolves to serveral ip-addresses. "
544 "Please specify one.", str);
546 *ip = ntohl(((struct in_addr *) host->h_addr_list[0])->s_addr);
550 exit_error(PARAMETER_PROBLEM, "host/network `%s' not found", str);
553 /* Fills 'mask' with the parsed mask in host byte order */
554 void parse_mask(const char *str, ip_set_ip_t * mask)
562 /* no mask at all defaults to 32 bits */
566 if (strchr(str, '.') && inet_aton(str, &addr) != 0) {
567 *mask = ntohl(addr.s_addr); /* We want host byte order */
570 if (sscanf(str, "%d", &bits) != 1 || bits < 0 || bits > 32)
571 exit_error(PARAMETER_PROBLEM,
572 "invalid mask `%s' specified", str);
574 DP("bits: %d", bits);
576 *mask = bits != 0 ? 0xFFFFFFFF << (32 - bits) : 0L;
579 /* Combines parse_ip and parse_mask */
581 parse_ipandmask(const char *str, ip_set_ip_t * ip, ip_set_ip_t * mask)
586 strncpy(buf, str, sizeof(buf) - 1);
589 if ((p = strrchr(buf, '/')) != NULL) {
591 parse_mask(p + 1, mask);
593 parse_mask(NULL, mask);
595 /* if a null mask is given, the name is ignored, like in "any/0" */
601 DP("%s ip: %08X (%s) mask: %08X",
602 str, *ip, ip_tostring_numeric(*ip), *mask);
604 /* Apply the netmask */
607 DP("%s ip: %08X (%s) mask: %08X",
608 str, *ip, ip_tostring_numeric(*ip), *mask);
611 /* Return a string representation of a port
612 * Please notice that a pointer to static char* area is returned
613 * and we assume TCP protocol.
615 char *port_tostring(ip_set_ip_t port, unsigned options)
617 struct servent *service;
618 static char name[] = "65535";
620 if (!(options & OPT_NUMERIC)) {
621 if ((service = getservbyport(htons(port), "tcp")))
622 return service->s_name;
624 sprintf(name, "%u", port);
629 string_to_number(const char *str, unsigned int min, unsigned int max,
635 /* Handle hex, octal, etc. */
637 number = strtol(str, &end, 0);
638 if (*end == '\0' && end != str) {
639 /* we parsed a number, let's see if we want this */
640 if (errno != ERANGE && min <= number && number <= max) {
649 string_to_port(const char *str, ip_set_ip_t *port)
651 struct servent *service;
653 if ((service = getservbyname(str, "tcp")) != NULL) {
654 *port = ntohs((unsigned short) service->s_port);
661 /* Fills the 'ip' with the parsed port in host byte order */
662 void parse_port(const char *str, ip_set_ip_t *port)
664 if ((string_to_number(str, 0, 65535, port) != 0)
665 && (string_to_port(str, port) != 0))
666 exit_error(PARAMETER_PROBLEM,
667 "Invalid TCP port `%s' specified", str);
673 static struct settype *settype_find(const char *typename)
675 struct settype *runner = all_settypes;
679 while (runner != NULL) {
680 if (strncmp(runner->typename, typename,
681 IP_SET_MAXNAMELEN) == 0)
684 runner = runner->next;
687 return NULL; /* not found */
690 static struct settype *settype_load(const char *typename)
692 char path[sizeof(IPSET_LIB_DIR) + sizeof(IPSET_LIB_NAME) +
694 struct settype *settype;
696 /* do some search in list */
697 settype = settype_find(typename);
699 return settype; /* found */
701 /* Else we have to load it */
702 sprintf(path, IPSET_LIB_DIR IPSET_LIB_NAME, typename);
704 if (dlopen(path, RTLD_NOW)) {
707 settype = settype_find(typename);
713 /* Can't load the settype */
714 exit_error(PARAMETER_PROBLEM,
715 "Couldn't load settype `%s':%s\n",
716 typename, dlerror());
718 return NULL; /* Never executed, but keep compilers happy */
721 static char *check_set_name(char *setname)
723 if (strlen(setname) > IP_SET_MAXNAMELEN - 1)
724 exit_error(PARAMETER_PROBLEM,
725 "Setname '%s' too long, max %d characters.",
726 setname, IP_SET_MAXNAMELEN - 1);
731 static struct settype *check_set_typename(const char *typename)
733 if (strlen(typename) > IP_SET_MAXNAMELEN - 1)
734 exit_error(PARAMETER_PROBLEM,
735 "Typename '%s' too long, max %d characters.",
736 typename, IP_SET_MAXNAMELEN - 1);
738 return settype_load(typename);
741 #define MAX(a,b) ((a) > (b) ? (a) : (b))
743 /* Register a new set type */
744 void settype_register(struct settype *settype)
749 DP("%s", settype->typename);
751 /* Check if this typename already exists */
752 chk = settype_find(settype->typename);
755 exit_error(OTHER_PROBLEM,
756 "Set type '%s' already registered!\n",
760 if (settype->protocol_version != IP_SET_PROTOCOL_VERSION)
761 exit_error(OTHER_PROBLEM,
762 "Set type %s is of wrong protocol version %u!"
763 " I'm of version %u.\n", settype->typename,
764 settype->protocol_version,
765 IP_SET_PROTOCOL_VERSION);
767 /* Initialize internal data */
768 settype->header = ipset_malloc(settype->header_size);
769 size = MAX(settype->create_size, settype->adt_size);
770 settype->data = ipset_malloc(size);
773 settype->next = all_settypes;
774 all_settypes = settype;
776 DP("%s registered", settype->typename);
779 /* Find set functions */
780 static struct set *set_find_byid(ip_set_id_t id)
782 struct set *set = NULL;
785 for (i = 0; i < max_sets; i++)
786 if (set_list[i] && set_list[i]->id == id) {
792 exit_error(PARAMETER_PROBLEM,
793 "Set identified by id %u is not found", id);
797 static struct set *set_find_byname(const char *name)
799 struct set *set = NULL;
802 for (i = 0; i < max_sets; i++)
804 && strncmp(set_list[i]->name, name,
805 IP_SET_MAXNAMELEN) == 0) {
810 exit_error(PARAMETER_PROBLEM,
811 "Set %s is not found", name);
815 static ip_set_id_t set_find_free_index(const char *name)
817 ip_set_id_t i, index = IP_SET_INVALID_ID;
819 for (i = 0; i < max_sets; i++) {
820 if (index == IP_SET_INVALID_ID
821 && set_list[i] == NULL)
823 if (set_list[i] != NULL
824 && strncmp(set_list[i]->name, name,
825 IP_SET_MAXNAMELEN) == 0)
826 exit_error(PARAMETER_PROBLEM,
827 "Set %s is already defined, cannot be restored",
831 if (index == IP_SET_INVALID_ID)
832 exit_error(PARAMETER_PROBLEM,
833 "Set %s cannot be restored, "
834 "max number of set %u reached",
841 * Send create set order to kernel
843 static void set_create(const char *name, struct settype *settype)
845 struct ip_set_req_create req_create;
849 DP("%s %s", name, settype->typename);
851 req_create.op = IP_SET_OP_CREATE;
852 req_create.version = IP_SET_PROTOCOL_VERSION;
853 strcpy(req_create.name, name);
854 strcpy(req_create.typename, settype->typename);
857 settype->create_final(settype->data, settype->flags);
859 /* Alloc memory for the data to send */
860 size = sizeof(struct ip_set_req_create) + settype->create_size;
861 data = ipset_malloc(size);
863 /* Add up ip_set_req_create and the settype data */
864 memcpy(data, &req_create, sizeof(struct ip_set_req_create));
865 memcpy(data + sizeof(struct ip_set_req_create),
866 settype->data, settype->create_size);
868 kernel_sendto(CMD_CREATE, data, size);
872 static void set_restore_create(const char *name, struct settype *settype)
876 DP("%s %s %u %u %u %u", name, settype->typename,
877 restore_offset, sizeof(struct ip_set_restore),
878 settype->create_size, restore_size);
880 /* Sanity checking */
882 + sizeof(struct ip_set_restore)
883 + settype->create_size > restore_size)
884 exit_error(PARAMETER_PROBLEM,
885 "Giving up, restore file is screwed up!");
888 settype->create_final(settype->data, settype->flags);
890 /* Fill out restore_data */
891 restore_set = (struct ip_set_restore *)
892 (restore_data + restore_offset);
893 strcpy(restore_set->name, name);
894 strcpy(restore_set->typename, settype->typename);
895 restore_set->index = set_find_free_index(name);
896 restore_set->header_size = settype->create_size;
897 restore_set->members_size = 0;
899 DP("name %s, restore index %u", restore_set->name, restore_set->index);
900 /* Add settype data */
902 memcpy(restore_data + restore_offset + sizeof(struct ip_set_restore),
903 settype->data, settype->create_size);
905 restore_offset += sizeof(struct ip_set_restore)
906 + settype->create_size;
908 /* Add set to set_list */
909 set = ipset_malloc(sizeof(struct set));
910 strcpy(set->name, name);
911 set->settype = settype;
912 set->index = restore_set->index;
913 set_list[restore_set->index] = set;
917 * Send destroy/flush order to kernel for one or all sets
919 static void set_destroy(const char *name, unsigned op, unsigned cmd)
921 struct ip_set_req_std req;
923 DP("%s %s", cmd == CMD_DESTROY ? "destroy" : "flush", name);
926 req.version = IP_SET_PROTOCOL_VERSION;
927 strcpy(req.name, name);
929 kernel_sendto(cmd, &req, sizeof(struct ip_set_req_std));
933 * Send rename/swap order to kernel
935 static void set_rename(const char *name, const char *newname,
936 unsigned op, unsigned cmd)
938 struct ip_set_req_create req;
940 DP("%s %s %s", cmd == CMD_RENAME ? "rename" : "swap",
944 req.version = IP_SET_PROTOCOL_VERSION;
945 strcpy(req.name, name);
946 strcpy(req.typename, newname);
948 kernel_sendto(cmd, &req,
949 sizeof(struct ip_set_req_create));
953 * Send MAX_SETS, LIST_SIZE and/or SAVE_SIZE orders to kernel
955 static size_t load_set_list(const char name[IP_SET_MAXNAMELEN],
957 unsigned op, unsigned cmd)
960 struct ip_set_req_max_sets req_max_sets;
961 struct ip_set_name_list *name_list;
964 size_t size, req_size;
965 int repeated = 0, res = 0;
967 DP("%s %s", cmd == CMD_MAX_SETS ? "MAX_SETS"
968 : cmd == CMD_LIST_SIZE ? "LIST_SIZE"
974 for (i = 0; i < max_sets; i++)
981 req_max_sets.op = IP_SET_OP_MAX_SETS;
982 req_max_sets.version = IP_SET_PROTOCOL_VERSION;
983 strcpy(req_max_sets.set.name, name);
984 size = sizeof(req_max_sets);
985 kernel_getfrom(CMD_MAX_SETS, &req_max_sets, &size);
987 DP("got MAX_SETS: sets %d, max_sets %d",
988 req_max_sets.sets, req_max_sets.max_sets);
990 max_sets = req_max_sets.max_sets;
991 set_list = ipset_malloc(max_sets * sizeof(struct set *));
992 memset(set_list, 0, max_sets * sizeof(struct set *));
993 *index = req_max_sets.set.index;
995 if (req_max_sets.sets == 0)
996 /* No sets in kernel */
1000 size = req_size = sizeof(struct ip_set_req_setnames)
1001 + req_max_sets.sets * sizeof(struct ip_set_name_list);
1002 data = ipset_malloc(size);
1003 ((struct ip_set_req_setnames *) data)->op = op;
1004 ((struct ip_set_req_setnames *) data)->index = *index;
1006 res = kernel_getfrom_handleerrno(cmd, data, &size);
1008 if (res != 0 || size != req_size) {
1010 if (repeated++ < LIST_TRIES)
1012 exit_error(OTHER_PROBLEM,
1013 "Tried to get sets from kernel %d times"
1014 " and failed. Please try again when the load on"
1015 " the sets has gone down.", LIST_TRIES);
1018 /* Load in setnames */
1019 size = sizeof(struct ip_set_req_setnames);
1020 while (size + sizeof(struct ip_set_name_list) <= req_size) {
1021 name_list = (struct ip_set_name_list *)
1023 set = ipset_malloc(sizeof(struct set));
1024 strcpy(set->name, name_list->name);
1025 set->index = name_list->index;
1026 set->id = name_list->id;
1027 set->settype = settype_load(name_list->typename);
1028 set_list[name_list->index] = set;
1029 DP("loaded %s, type %s, index %u",
1030 set->name, set->settype->typename, set->index);
1031 size += sizeof(struct ip_set_name_list);
1033 /* Size to get set members, bindings */
1034 size = ((struct ip_set_req_setnames *)data)->size;
1043 static size_t save_bindings(void *data, size_t offset, size_t len)
1045 struct ip_set_hash_save *hash =
1046 (struct ip_set_hash_save *) (data + offset);
1049 DP("offset %u, len %u", offset, len);
1050 if (offset + sizeof(struct ip_set_hash_save) > len)
1051 exit_error(OTHER_PROBLEM,
1052 "Save operation failed, try again later.");
1054 set = set_find_byid(hash->id);
1055 if (!(set && set_list[hash->binding]))
1056 exit_error(OTHER_PROBLEM,
1057 "Save binding failed, try again later.");
1058 printf("-B %s %s -b %s\n",
1060 set->settype->bindip_tostring(set, hash->ip, OPT_NUMERIC),
1061 set_list[hash->binding]->name);
1063 return sizeof(struct ip_set_hash_save);
1066 static size_t save_set(void *data, int *bindings,
1067 size_t offset, size_t len)
1069 struct ip_set_save *set_save =
1070 (struct ip_set_save *) (data + offset);
1072 struct settype *settype;
1075 DP("offset %u, len %u", offset, len);
1076 if (offset + sizeof(struct ip_set_save) > len
1077 || offset + sizeof(struct ip_set_save)
1078 + set_save->header_size + set_save->members_size > len)
1079 exit_error(OTHER_PROBLEM,
1080 "Save operation failed, try again later.");
1082 if (set_save->index == IP_SET_INVALID_ID) {
1085 return sizeof(struct ip_set_save);
1087 set = set_list[set_save->index];
1089 exit_error(OTHER_PROBLEM,
1090 "Save set failed, try again later.");
1091 settype = set->settype;
1093 /* Init set header */
1094 used = sizeof(struct ip_set_save);
1095 settype->initheader(set, data + offset + used);
1097 /* Print create set */
1098 settype->saveheader(set, OPT_NUMERIC);
1101 used += set_save->header_size;
1102 settype->saveips(set, data + offset + used,
1103 set_save->members_size, OPT_NUMERIC);
1105 return (used + set_save->members_size);
1108 static size_t save_default_bindings(void *data, int *bindings)
1110 struct ip_set_save *set_save = (struct ip_set_save *) data;
1113 if (set_save->index == IP_SET_INVALID_ID) {
1116 return sizeof(struct ip_set_save);
1119 set = set_list[set_save->index];
1120 DP("%s, binding %u", set->name, set_save->binding);
1121 if (set_save->binding != IP_SET_INVALID_ID) {
1122 if (!set_list[set_save->binding])
1123 exit_error(OTHER_PROBLEM,
1124 "Save set failed, try again later.");
1126 printf("-B %s %s -b %s\n",
1127 set->name, IPSET_TOKEN_DEFAULT,
1128 set_list[set_save->binding]->name);
1130 return (sizeof(struct ip_set_save)
1131 + set_save->header_size
1132 + set_save->members_size);
1135 static int try_save_sets(const char name[IP_SET_MAXNAMELEN])
1138 size_t size, req_size = 0;
1140 int res = 0, bindings = 0;
1141 time_t now = time(NULL);
1143 /* Load set_list from kernel */
1144 size = load_set_list(name, &index,
1145 IP_SET_OP_SAVE_SIZE, CMD_SAVE);
1148 /* Get sets, bindings and print them */
1149 /* Take into account marker */
1150 req_size = (size += sizeof(struct ip_set_save));
1151 data = ipset_malloc(size);
1152 ((struct ip_set_req_list *) data)->op = IP_SET_OP_SAVE;
1153 ((struct ip_set_req_list *) data)->index = index;
1154 res = kernel_getfrom_handleerrno(CMD_SAVE, data, &size);
1156 if (res != 0 || size != req_size) {
1162 printf("# Generated by ipset %s on %s", IPSET_VERSION, ctime(&now));
1164 while (size < req_size) {
1165 DP("size: %u, req_size: %u", size, req_size);
1167 size += save_bindings(data, size, req_size);
1169 size += save_set(data, &bindings, size, req_size);
1171 /* Re-read data to save default bindings */
1174 while (size < req_size && bindings == 0)
1175 size += save_default_bindings(data + size, &bindings);
1179 printf("# Completed on %s", ctime(&now));
1185 * Performs a save to stdout
1187 static void set_save(const char name[IP_SET_MAXNAMELEN])
1192 for (i = 0; i < LIST_TRIES; i++)
1193 if (try_save_sets(name) == 0)
1196 if (errno == EAGAIN)
1197 exit_error(OTHER_PROBLEM,
1198 "Tried to save sets from kernel %d times"
1199 " and failed. Please try again when the load on"
1200 " the sets has gone down.", LIST_TRIES);
1202 kernel_error(CMD_SAVE, errno);
1209 /* global new argv and argc */
1210 static char *newargv[255];
1211 static int newargc = 0;
1213 /* Build faked argv from parsed line */
1214 static void build_argv(int line, char *buffer) {
1219 for (i = 1; i < newargc; i++)
1223 ptr = strtok(buffer, " \t\n");
1224 newargv[newargc++] = ipset_strdup(ptr);
1225 while ((ptr = strtok(NULL, " \t\n")) != NULL) {
1226 if ((newargc + 1) < sizeof(newargv)/sizeof(char *))
1227 newargv[newargc++] = ipset_strdup(ptr);
1229 exit_error(PARAMETER_PROBLEM,
1230 "Line %d is too long to restore\n", line);
1234 static FILE *create_tempfile(void)
1237 char *tmpdir = NULL;
1242 if (!(tmpdir = getenv("TMPDIR")) && !(tmpdir = getenv("TMP")))
1244 filename = ipset_malloc(strlen(tmpdir) + strlen(TEMPFILE_PATTERN) + 1);
1245 strcpy(filename, tmpdir);
1246 strcat(filename, TEMPFILE_PATTERN);
1248 (void) umask(077); /* Create with restrictive permissions */
1249 fd = mkstemp(filename);
1251 exit_error(OTHER_PROBLEM, "Could not create temporary file.");
1252 if (!(file = fdopen(fd, "r+")))
1253 exit_error(OTHER_PROBLEM, "Could not open temporary file.");
1254 if (unlink(filename) == -1)
1255 exit_error(OTHER_PROBLEM, "Could not unlink temporary file.");
1258 while (fgets(buffer, sizeof(buffer), stdin)) {
1259 fputs(buffer, file);
1261 fseek(file, 0L, SEEK_SET);
1267 * Performs a restore from a file
1269 static void set_restore(char *argv0)
1272 char *ptr, *name = NULL;
1274 int line = 0, first_pass, i, bindings = 0;
1275 struct settype *settype = NULL;
1276 struct ip_set_req_setnames *header;
1281 /* Create and store stdin in temporary file */
1282 in = create_tempfile();
1284 /* Load existing sets from kernel */
1285 load_set_list(IPSET_TOKEN_ALL, &index,
1286 IP_SET_OP_LIST_SIZE, CMD_RESTORE);
1288 restore_size = sizeof(struct ip_set_req_setnames)/* header */
1289 + sizeof(struct ip_set_restore); /* marker */
1290 DP("restore_size: %u", restore_size);
1291 /* First pass: calculate required amount of data */
1292 while (fgets(buffer, sizeof(buffer), in)) {
1295 if (buffer[0] == '\n')
1297 else if (buffer[0] == '#')
1299 else if (strcmp(buffer, "COMMIT\n") == 0) {
1300 /* Enable restore mode */
1306 ptr = strtok(buffer, " \t\n");
1313 || ptr[2] != '\0') {
1314 exit_error(PARAMETER_PROBLEM,
1315 "Line %u does not start as a valid restore command\n",
1320 ptr = strtok(NULL, " \t\n");
1321 DP("setname: %s", ptr);
1323 exit_error(PARAMETER_PROBLEM,
1324 "Missing set name in line %u\n",
1329 name = check_set_name(ptr);
1331 ptr = strtok(NULL, " \t\n");
1333 exit_error(PARAMETER_PROBLEM,
1334 "Missing settype in line %u\n",
1337 exit_error(PARAMETER_PROBLEM,
1338 "Invalid line %u: create must precede bindings\n",
1340 settype = check_set_typename(ptr);
1341 restore_size += sizeof(struct ip_set_restore)
1342 + settype->create_size;
1343 DP("restore_size (N): %u", restore_size);
1348 || strncmp(name, ptr, sizeof(name)) != 0)
1349 exit_error(PARAMETER_PROBLEM,
1350 "Add IP to set %s in line %u without "
1351 "preceding corresponding create set line\n",
1354 exit_error(PARAMETER_PROBLEM,
1355 "Invalid line %u: adding entries must precede bindings\n",
1357 restore_size += settype->adt_size;
1358 DP("restore_size (A): %u", restore_size);
1363 restore_size += sizeof(struct ip_set_hash_save);
1364 DP("restore_size (B): %u", restore_size);
1368 exit_error(PARAMETER_PROBLEM,
1369 "Unrecognized restore command in line %u\n",
1372 } /* end of switch */
1374 /* Sanity checking */
1376 exit_error(PARAMETER_PROBLEM,
1377 "Missing COMMIT line\n");
1378 DP("restore_size: %u", restore_size);
1379 restore_data = ipset_malloc(restore_size);
1380 header = (struct ip_set_req_setnames *) restore_data;
1381 header->op = IP_SET_OP_RESTORE;
1382 header->size = restore_size;
1383 restore_offset = sizeof(struct ip_set_req_setnames);
1385 /* Rewind to scan the file again */
1386 fseek(in, 0L, SEEK_SET);
1390 /* Initialize newargv/newargc */
1391 newargv[newargc++] = ipset_strdup(argv0);
1393 /* Second pass: build up restore request */
1394 while (fgets(buffer, sizeof(buffer), in)) {
1397 if (buffer[0] == '\n')
1399 else if (buffer[0] == '#')
1401 else if (strcmp(buffer, "COMMIT\n") == 0)
1403 DP("restoring: %s", buffer);
1404 /* Build faked argv, argc */
1405 build_argv(line, buffer);
1406 for (i = 0; i < newargc; i++)
1407 DP("argv[%u]: %s", i, newargv[i]);
1410 parse_commandline(newargc, newargv);
1412 exit_error(PARAMETER_PROBLEM,
1413 "Broken restore file\n");
1417 (restore_offset + sizeof(struct ip_set_restore))) {
1419 struct ip_set_restore *marker =
1420 (struct ip_set_restore *) (restore_data + restore_offset);
1422 DP("restore marker");
1423 marker->index = IP_SET_INVALID_ID;
1424 marker->header_size = marker->members_size = 0;
1425 restore_offset += sizeof(struct ip_set_restore);
1427 if (restore_size != restore_offset)
1428 exit_error(PARAMETER_PROBLEM,
1429 "Giving up, restore file is screwed up!");
1430 res = kernel_getfrom_handleerrno(CMD_RESTORE, restore_data, &restore_size);
1433 if (restore_size != sizeof(struct ip_set_req_setnames))
1434 exit_error(PARAMETER_PROBLEM,
1435 "Communication with kernel failed (%u %u)!",
1436 restore_size, sizeof(struct ip_set_req_setnames));
1438 header = (struct ip_set_req_setnames *) restore_data;
1439 if (header->size != 0)
1440 exit_error(PARAMETER_PROBLEM,
1441 "Committing restoring failed at line %u!",
1447 * Send ADT_GET order to kernel for a set
1449 static struct set *set_adt_get(const char *name)
1451 struct ip_set_req_adt_get req_adt_get;
1457 req_adt_get.op = IP_SET_OP_ADT_GET;
1458 req_adt_get.version = IP_SET_PROTOCOL_VERSION;
1459 strcpy(req_adt_get.set.name, name);
1460 size = sizeof(struct ip_set_req_adt_get);
1462 kernel_getfrom(CMD_ADT_GET, &req_adt_get, &size);
1464 set = ipset_malloc(sizeof(struct set));
1465 strcpy(set->name, name);
1466 set->index = req_adt_get.set.index;
1467 set->settype = settype_load(req_adt_get.typename);
1473 * Send add/del/test order to kernel for a set
1475 static int set_adtip(struct set *set, const char *adt,
1476 unsigned op, unsigned cmd)
1478 struct ip_set_req_adt *req_adt;
1483 DP("%s -> %s", set->name, adt);
1485 /* Alloc memory for the data to send */
1486 size = sizeof(struct ip_set_req_adt) + set->settype->adt_size ;
1487 DP("alloc size %i", size);
1488 data = ipset_malloc(size);
1490 /* Fill out the request */
1491 req_adt = (struct ip_set_req_adt *) data;
1493 req_adt->index = set->index;
1494 memcpy(data + sizeof(struct ip_set_req_adt),
1495 set->settype->data, set->settype->adt_size);
1497 if (kernel_sendto_handleerrno(cmd, op, data, size) == -1)
1499 case IP_SET_OP_ADD_IP:
1500 exit_error(OTHER_PROBLEM, "%s is already in set %s.",
1503 case IP_SET_OP_DEL_IP:
1504 exit_error(OTHER_PROBLEM, "%s is not in set %s.",
1507 case IP_SET_OP_TEST_IP:
1508 ipset_printf("%s is in set %s.", adt, set->name);
1516 case IP_SET_OP_TEST_IP:
1517 ipset_printf("%s is NOT in set %s.", adt, set->name);
1528 static void set_restore_add(struct set *set, const char *adt)
1530 DP("%s %s", set->name, adt);
1531 /* Sanity checking */
1532 if (restore_offset + set->settype->adt_size > restore_size)
1533 exit_error(PARAMETER_PROBLEM,
1534 "Giving up, restore file is screwed up!");
1536 memcpy(restore_data + restore_offset,
1537 set->settype->data, set->settype->adt_size);
1538 restore_set->members_size += set->settype->adt_size;
1539 restore_offset += set->settype->adt_size;
1543 * Send bind/unbind/test binding order to kernel for a set
1545 static int set_bind(struct set *set, const char *adt,
1546 const char *binding,
1547 unsigned op, unsigned cmd)
1549 struct ip_set_req_bind *req_bind;
1554 /* set may be null: '-U :all: :all:|:default:' */
1555 DP("(%s, %s) -> %s", set ? set->name : IPSET_TOKEN_ALL, adt, binding);
1557 /* Alloc memory for the data to send */
1558 size = sizeof(struct ip_set_req_bind);
1559 if (op != IP_SET_OP_UNBIND_SET && adt[0] == ':')
1560 /* Set default binding */
1561 size += IP_SET_MAXNAMELEN;
1562 else if (!(op == IP_SET_OP_UNBIND_SET && set == NULL))
1563 size += set->settype->adt_size;
1564 DP("alloc size %i", size);
1565 data = ipset_malloc(size);
1567 /* Fill out the request */
1568 req_bind = (struct ip_set_req_bind *) data;
1570 req_bind->index = set ? set->index : IP_SET_INVALID_ID;
1571 if (adt[0] == ':') {
1572 /* ':default:' and ':all:' */
1573 strncpy(req_bind->binding, adt, IP_SET_MAXNAMELEN);
1574 if (op != IP_SET_OP_UNBIND_SET && adt[0] == ':')
1575 strncpy(data + sizeof(struct ip_set_req_bind),
1576 binding, IP_SET_MAXNAMELEN);
1578 strncpy(req_bind->binding, binding, IP_SET_MAXNAMELEN);
1579 memcpy(data + sizeof(struct ip_set_req_bind),
1580 set->settype->data, set->settype->adt_size);
1583 if (op == IP_SET_OP_TEST_BIND_SET) {
1584 if (kernel_sendto_handleerrno(cmd, op, data, size) == -1) {
1585 ipset_printf("%s in set %s is bound to %s.",
1586 adt, set->name, binding);
1589 ipset_printf("%s in set %s is NOT bound to %s.",
1590 adt, set->name, binding);
1594 kernel_sendto(cmd, data, size);
1600 static void set_restore_bind(struct set *set,
1602 const char *binding)
1604 struct ip_set_hash_save *hash_restore;
1608 struct ip_set_restore *marker =
1609 (struct ip_set_restore *) (restore_data + restore_offset);
1611 DP("restore marker");
1612 if (restore_offset + sizeof(struct ip_set_restore)
1614 exit_error(PARAMETER_PROBLEM,
1615 "Giving up, restore file is screwed up!");
1616 marker->index = IP_SET_INVALID_ID;
1617 marker->header_size = marker->members_size = 0;
1618 restore_offset += sizeof(struct ip_set_restore);
1621 /* Sanity checking */
1622 if (restore_offset + sizeof(struct ip_set_hash_save) > restore_size)
1623 exit_error(PARAMETER_PROBLEM,
1624 "Giving up, restore file is screwed up!");
1626 hash_restore = (struct ip_set_hash_save *) (restore_data + restore_offset);
1627 DP("%s -> %s", adt, binding);
1628 if (strcmp(adt, IPSET_TOKEN_DEFAULT) == 0)
1629 hash_restore->ip = 0;
1631 set->settype->bindip_parse(adt, &hash_restore->ip);
1632 hash_restore->id = set->index;
1633 hash_restore->binding = (set_find_byname(binding))->index;
1634 DP("id %u, ip %u, binding %u",
1635 hash_restore->id, hash_restore->ip, hash_restore->binding);
1636 restore_offset += sizeof(struct ip_set_hash_save);
1643 static void print_bindings(struct set *set,
1644 void *data, size_t size, unsigned options,
1645 char * (*printip)(struct set *set,
1646 ip_set_ip_t ip, unsigned options))
1649 struct ip_set_hash_list *hash;
1651 while (offset < size) {
1652 hash = (struct ip_set_hash_list *) (data + offset);
1653 printf("%s -> %s\n",
1654 printip(set, hash->ip, options),
1655 set_list[hash->binding]->name);
1656 offset += sizeof(struct ip_set_hash_list);
1660 /* Help function to set_list() */
1661 static size_t print_set(void *data, unsigned options)
1663 struct ip_set_list *setlist = (struct ip_set_list *) data;
1664 struct set *set = set_list[setlist->index];
1665 struct settype *settype = set->settype;
1668 /* Pretty print the set */
1669 printf("Name: %s\n", set->name);
1670 printf("Type: %s\n", settype->typename);
1671 printf("References: %d\n", setlist->ref);
1672 printf("Default binding: %s\n",
1673 setlist->binding == IP_SET_INVALID_ID ? ""
1674 : set_list[setlist->binding]->name);
1677 offset = sizeof(struct ip_set_list);
1678 settype->initheader(set, data + offset);
1680 /* Pretty print the type header */
1682 settype->printheader(set, options);
1684 /* Pretty print all IPs */
1685 printf("Members:\n");
1686 offset += setlist->header_size;
1687 if (options & OPT_SORTED)
1688 settype->printips_sorted(set, data + offset,
1689 setlist->members_size, options);
1691 settype->printips(set, data + offset,
1692 setlist->members_size, options);
1694 /* Print bindings */
1695 printf("Bindings:\n");
1696 offset += setlist->members_size;
1698 data + offset, setlist->bindings_size, options,
1699 settype->bindip_tostring);
1701 printf("\n"); /* One newline between sets */
1703 return (offset + setlist->bindings_size);
1706 static int try_list_sets(const char name[IP_SET_MAXNAMELEN],
1711 size_t size, req_size;
1715 /* Load set_list from kernel */
1716 size = req_size = load_set_list(name, &index,
1717 IP_SET_OP_LIST_SIZE, CMD_LIST);
1720 /* Get sets and print them */
1721 data = ipset_malloc(size);
1722 ((struct ip_set_req_list *) data)->op = IP_SET_OP_LIST;
1723 ((struct ip_set_req_list *) data)->index = index;
1724 res = kernel_getfrom_handleerrno(CMD_LIST, data, &size);
1725 DP("get_lists getsockopt() res=%d errno=%d", res, errno);
1727 if (res != 0 || size != req_size) {
1733 while (size != req_size)
1734 size += print_set(data + size, options);
1740 /* Print a set or all sets
1741 * All sets: name = NULL
1743 static void list_sets(const char name[IP_SET_MAXNAMELEN], unsigned options)
1748 for (i = 0; i < LIST_TRIES; i++)
1749 if (try_list_sets(name, options) == 0)
1752 if (errno == EAGAIN)
1753 exit_error(OTHER_PROBLEM,
1754 "Tried to list sets from kernel %d times"
1755 " and failed. Please try again when the load on"
1756 " the sets has gone down.", LIST_TRIES);
1758 kernel_error(CMD_LIST, errno);
1762 * If settype is non null help for that type is printed as well
1764 static void set_help(const struct settype *settype)
1768 " --debug -z Enable debugging\n\n";
1770 char debughelp[] = "\n";
1774 "Usage: %s -N new-set settype [options]\n"
1775 " %s -[XFLSH] [set] [options]\n"
1776 " %s -[EW] from-set to-set\n"
1777 " %s -[ADTU] set IP\n"
1778 " %s -B set IP option\n"
1780 " %s -h (print this help information)\n\n",
1781 program_name, program_version,
1782 program_name, program_name, program_name,
1783 program_name, program_name, program_name,
1786 printf("Commands:\n"
1787 "Either long or short options are allowed.\n"
1788 " --create -N setname settype <options>\n"
1789 " Create a new set\n"
1790 " --destroy -X [setname]\n"
1791 " Destroy a set or all sets\n"
1792 " --flush -F [setname]\n"
1793 " Flush a set or all sets\n"
1794 " --rename -E from-set to-set\n"
1795 " Rename from-set to to-set\n"
1796 " --swap -W from-set to-set\n"
1797 " Swap the content of two existing sets\n"
1798 " --list -L [setname] [options]\n"
1799 " List the IPs in a set or all sets\n"
1800 " --save -S [setname]\n"
1801 " Save the set or all sets to stdout\n"
1802 " --restore -R [option]\n"
1803 " Restores a saved state\n"
1804 " --add -A setname IP\n"
1805 " Add an IP to a set\n"
1806 " --del -D setname IP\n"
1807 " Deletes an IP from a set\n"
1808 " --test -T setname IP \n"
1809 " Tests if an IP exists in a set.\n"
1810 " --bind -B setname IP|:default: -b bind-setname\n"
1811 " Bind the IP in setname to bind-setname.\n"
1812 " --unbind -U setname IP|:all:|:default:\n"
1813 " Delete binding belonging to IP,\n"
1814 " all bindings or default binding of setname.\n"
1815 " --unbind -U :all: :all:|:default:\n"
1816 " Delete all bindings or all default bindings.\n"
1817 " --help -H [settype]\n"
1818 " Prints this help, and settype specific help\n"
1820 " Prints version information\n\n"
1822 " --sorted -s Numeric sort of the IPs in -L\n"
1823 " --numeric -n Numeric output of addresses in a -L\n"
1824 " --quiet -q Suppress any output to stdout and stderr.\n"
1825 " --binding -b Specifies the binding for -B\n");
1828 if (settype != NULL) {
1829 printf("Type '%s' specific:\n", settype->typename);
1834 static int find_cmd(const char option)
1838 for (i = 1; i <= NUMBER_OF_CMD; i++)
1839 if (cmdflags[i] == option)
1845 static int parse_adt_cmdline(unsigned command,
1849 struct settype **settype)
1853 /* -U :all: :all:|:default: */
1854 if (command == CMD_UNBIND) {
1855 if (strcmp(name, IPSET_TOKEN_ALL) == 0) {
1856 if (strcmp(adt, IPSET_TOKEN_DEFAULT) == 0
1857 || strcmp(adt, IPSET_TOKEN_ALL) == 0) {
1862 exit_error(PARAMETER_PROBLEM,
1863 "-U %s requires %s or %s as binding name",
1865 IPSET_TOKEN_DEFAULT,
1869 *set = restore ? set_find_byname(name)
1870 : set_adt_get(name);
1872 /* Reset space for adt data */
1873 *settype = (*set)->settype;
1874 memset((*settype)->data, 0, (*settype)->adt_size);
1876 if ((command == CMD_TEST
1877 || command == CMD_BIND
1878 || command == CMD_UNBIND)
1879 && (strcmp(adt, IPSET_TOKEN_DEFAULT) == 0
1880 || strcmp(adt, IPSET_TOKEN_ALL) == 0))
1883 res = (*settype)->adt_parser(
1891 /* Main worker function */
1892 int parse_commandline(int argc, char *argv[])
1895 unsigned command = CMD_NONE;
1896 unsigned options = 0;
1899 char *name = NULL; /* All except -H, -R */
1900 char *newname = NULL; /* -E, -W */
1901 char *adt = NULL; /* -A, -D, -T, -B, -U */
1902 char *binding = NULL; /* -B */
1903 struct set *set = NULL; /* -A, -D, -T, -B, -U */
1904 struct settype *settype = NULL; /* -N, -H */
1905 char all_sets[] = IPSET_TOKEN_ALL;
1907 struct option *opts = opts_long;
1909 /* Suppress error messages: we may add new options if we
1910 demand-load a protocol. */
1912 /* Reset optind to 0 for restore */
1915 while ((c = getopt_long(argc, argv, opts_short, opts, NULL)) != -1) {
1917 DP("commandline parsed: opt %c (%s)", c, argv[optind]);
1924 case 'H':{ /* Help: -H [typename [options]] */
1925 check_protocolversion();
1926 set_command(&command, CMD_HELP);
1929 settype = check_set_typename(optarg);
1930 else if (optind < argc
1931 && argv[optind][0] != '-')
1932 settype = check_set_typename(argv[optind++]);
1937 case 'V':{ /* Version */
1938 printf("%s v%s Protocol version %u.\n",
1939 program_name, program_version,
1940 IP_SET_PROTOCOL_VERSION);
1941 check_protocolversion();
1945 case 'N':{ /* Create: -N name typename options */
1946 set_command(&command, CMD_CREATE);
1948 name = check_set_name(optarg);
1950 /* Protect reserved names (binding) */
1952 exit_error(PARAMETER_PROBLEM,
1953 "setname might not start with colon",
1954 cmd2char(CMD_CREATE));
1957 && argv[optind][0] != '-')
1958 settype = check_set_typename(argv[optind++]);
1960 exit_error(PARAMETER_PROBLEM,
1961 "-%c requires setname and settype",
1962 cmd2char(CMD_CREATE));
1964 DP("merge options");
1965 /* Merge the create options */
1966 opts = merge_options(opts,
1967 settype->create_opts,
1968 &settype->option_offset);
1970 /* Reset space for create data */
1971 memset(settype->data, 0, settype->create_size);
1973 /* Zero the flags */
1976 DP("call create_init");
1977 /* Call the settype create_init */
1978 settype->create_init(settype->data);
1983 case 'X': /* Destroy */
1984 case 'F': /* Flush */
1985 case 'L': /* List */
1986 case 'S':{ /* Save */
1987 set_command(&command, find_cmd(c));
1990 name = check_set_name(optarg);
1991 else if (optind < argc
1992 && argv[optind][0] != '-')
1993 name = check_set_name(argv[optind++]);
2000 case 'R':{ /* Restore */
2001 set_command(&command, find_cmd(c));
2006 case 'E': /* Rename */
2007 case 'W':{ /* Swap */
2008 set_command(&command, find_cmd(c));
2009 name = check_set_name(optarg);
2012 && argv[optind][0] != '-')
2013 newname = check_set_name(argv[optind++]);
2015 exit_error(PARAMETER_PROBLEM,
2016 "-%c requires a setname "
2017 "and the new name for that set",
2018 cmd2char(CMD_RENAME));
2023 case 'A': /* Add IP */
2024 case 'D': /* Del IP */
2025 case 'T': /* Test IP */
2026 case 'B': /* Bind IP */
2027 case 'U':{ /* Unbind IP */
2028 set_command(&command, find_cmd(c));
2030 name = check_set_name(optarg);
2034 && argv[optind][0] != '-')
2035 adt = argv[optind++];
2037 exit_error(PARAMETER_PROBLEM,
2038 "-%c requires setname and IP",
2041 res = parse_adt_cmdline(command, name, adt,
2045 exit_error(PARAMETER_PROBLEM,
2055 add_option(&options, OPT_NUMERIC);
2059 add_option(&options, OPT_SORTED);
2063 add_option(&options, OPT_QUIET);
2068 case 'z': /* debug */
2069 add_option(&options, OPT_DEBUG);
2075 add_option(&options, OPT_BINDING);
2076 binding = check_set_name(optarg);
2079 case 1: /* non option */
2080 printf("Bad argument `%s'\n", optarg);
2082 break; /*always good */
2089 res = settype->create_parse(
2090 c - settype->option_offset,
2097 res = 0; /* failed */
2098 } /* switch (command) */
2102 exit_error(PARAMETER_PROBLEM,
2111 } /* while( getopt_long() ) */
2115 exit_error(PARAMETER_PROBLEM,
2116 "unknown arguments found on commandline");
2117 if (command == CMD_NONE)
2118 exit_error(PARAMETER_PROBLEM, "no command specified");
2121 generic_opt_check(command, options);
2123 DP("cmd: %c", cmd2char(command));
2129 set_restore_create(name, settype);
2131 set_create(name, settype);
2135 set_destroy(name, IP_SET_OP_DESTROY, CMD_DESTROY);
2139 set_destroy(name, IP_SET_OP_FLUSH, CMD_FLUSH);
2143 set_rename(name, newname, IP_SET_OP_RENAME, CMD_RENAME);
2147 set_rename(name, newname, IP_SET_OP_SWAP, CMD_SWAP);
2151 list_sets(name, options);
2159 set_restore(argv[0]);
2164 set_restore_add(set, adt);
2166 set_adtip(set, adt, IP_SET_OP_ADD_IP, CMD_ADD);
2170 set_adtip(set, adt, IP_SET_OP_DEL_IP, CMD_DEL);
2175 res = set_bind(set, adt, binding,
2176 IP_SET_OP_TEST_BIND_SET, CMD_TEST);
2178 res = set_adtip(set, adt,
2179 IP_SET_OP_TEST_IP, CMD_TEST);
2184 set_restore_bind(set, adt, binding);
2186 set_bind(set, adt, binding,
2187 IP_SET_OP_BIND_SET, CMD_BIND);
2191 set_bind(set, adt, "", IP_SET_OP_UNBIND_SET, CMD_UNBIND);
2199 /* Will never happen */
2200 break; /* Keep the compiler happy */
2202 } /* switch( command ) */
2208 int main(int argc, char *argv[])
2210 return parse_commandline(argc, argv);