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>
21 #include <arpa/inet.h>
26 /* #include <asm/bitops.h> */
30 #ifndef PROC_SYS_MODPROBE
31 #define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
34 char program_name[] = "ipset";
35 char program_version[] = IPSET_VERSION;
37 /* The list of loaded set types */
38 static struct settype *all_settypes = NULL;
41 struct set **set_list = NULL;
42 ip_set_id_t max_sets = 0;
44 /* Suppress output to stdout and stderr? */
45 static int option_quiet = 0;
47 /* Data for restore mode */
48 static int restore = 0;
49 void *restore_data = NULL;
50 struct ip_set_restore *restore_set = NULL;
51 size_t restore_offset = 0;
52 socklen_t restore_size;
55 #define TEMPFILE_PATTERN "/ipsetXXXXXX"
61 #define OPTION_OFFSET 256
62 static unsigned int global_option_offset = 0;
64 /* Most of these command parsing functions are borrowed from iptables.c */
66 static const char cmdflags[] = { ' ', /* CMD_NONE */
67 'N', 'X', 'F', 'E', 'W', 'L', 'S', 'R',
68 'A', 'D', 'T', 'B', 'U', 'H', 'V',
72 #define OPT_NONE 0x0000U
73 #define OPT_NUMERIC 0x0001U /* -n */
74 #define OPT_SORTED 0x0002U /* -s */
75 #define OPT_QUIET 0x0004U /* -q */
76 #define OPT_DEBUG 0x0008U /* -z */
77 #define OPT_BINDING 0x0010U /* -b */
78 #define NUMBER_OF_OPT 5
79 static const char optflags[] =
80 { 'n', 's', 'q', 'z', 'b' };
82 static struct option opts_long[] = {
84 {"create", 1, 0, 'N'},
85 {"destroy", 2, 0, 'X'},
87 {"rename", 1, 0, 'E'},
92 {"restore", 0, 0, 'R'},
94 /* ip in set operations */
99 /* binding operations */
101 {"unbind", 1, 0, 'U'},
104 {"numeric", 0, 0, 'n'},
105 {"sorted", 0, 0, 's'},
106 {"quiet", 0, 0, 'q'},
107 {"binding", 1, 0, 'b'},
110 /* debug (if compiled with it) */
111 {"debug", 0, 0, 'z'},
114 /* version and help */
115 {"version", 0, 0, 'V'},
122 static char opts_short[] =
123 "-N:X::F::E:W:L::S::RA:D:T:B:U:nsqzb:Vh::H::";
125 /* Table of legal combinations of commands and options. If any of the
126 * given commands make an option legal, that option is legal.
133 static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] = {
135 /*CREATE*/ {'x', 'x', ' ', ' ', 'x'},
136 /*DESTROY*/ {'x', 'x', ' ', ' ', 'x'},
137 /*FLUSH*/ {'x', 'x', ' ', ' ', 'x'},
138 /*RENAME*/ {'x', 'x', ' ', ' ', 'x'},
139 /*SWAP*/ {'x', 'x', ' ', ' ', 'x'},
140 /*LIST*/ {' ', ' ', 'x', ' ', 'x'},
141 /*SAVE*/ {'x', 'x', ' ', ' ', 'x'},
142 /*RESTORE*/ {'x', 'x', ' ', ' ', 'x'},
143 /*ADD*/ {'x', 'x', ' ', ' ', 'x'},
144 /*DEL*/ {'x', 'x', ' ', ' ', 'x'},
145 /*TEST*/ {'x', 'x', ' ', ' ', ' '},
146 /*BIND*/ {'x', 'x', ' ', ' ', '+'},
147 /*UNBIND*/ {'x', 'x', ' ', ' ', 'x'},
148 /*HELP*/ {'x', 'x', 'x', ' ', 'x'},
149 /*VERSION*/ {'x', 'x', 'x', ' ', 'x'},
152 /* Main parser function */
153 int parse_commandline(int argc, char *argv[]);
155 void exit_tryhelp(int status)
158 "Try `%s -H' or '%s --help' for more information.\n",
159 program_name, program_name);
163 void exit_error(enum exittype status, char *msg, ...)
169 fprintf(stderr, "%s v%s: ", program_name, program_version);
170 vfprintf(stderr, msg, args);
172 fprintf(stderr, "\n");
174 fprintf(stderr, "Restore failed at line %u:\n", line);
175 if (status == PARAMETER_PROBLEM)
176 exit_tryhelp(status);
177 if (status == VERSION_PROBLEM)
179 "Perhaps %s or your kernel needs to be upgraded.\n",
186 void ipset_printf(char *msg, ...)
192 vfprintf(stdout, msg, args);
194 fprintf(stdout, "\n");
198 static void generic_opt_check(int command, int options)
202 /* Check that commands are valid with options. Complicated by the
203 * fact that if an option is legal with *any* command given, it is
204 * legal overall (ie. -z and -l).
206 for (i = 0; i < NUMBER_OF_OPT; i++) {
207 legal = 0; /* -1 => illegal, 1 => legal, 0 => undecided. */
209 for (j = 1; j <= NUMBER_OF_CMD; j++) {
213 if (!(options & (1 << i))) {
214 if (commands_v_options[j-1][i] == '+')
215 exit_error(PARAMETER_PROBLEM,
216 "You need to supply the `-%c' "
217 "option for this command\n",
220 if (commands_v_options[j-1][i] != 'x')
227 exit_error(PARAMETER_PROBLEM,
228 "Illegal option `-%c' with this command\n",
233 static char opt2char(int option)
236 for (ptr = optflags; option > 1; option >>= 1, ptr++);
241 static char cmd2char(int option)
243 if (option <= CMD_NONE || option > NUMBER_OF_CMD)
246 return cmdflags[option];
249 /* From iptables.c ... */
250 static char *get_modprobe(void)
255 #define PROCFILE_BUFSIZ 1024
256 procfile = open(PROC_SYS_MODPROBE, O_RDONLY);
260 ret = (char *) malloc(PROCFILE_BUFSIZ);
262 memset(ret, 0, PROCFILE_BUFSIZ);
263 switch (read(procfile, ret, PROCFILE_BUFSIZ)) {
265 case PROCFILE_BUFSIZ: goto fail; /* Partial read. Wierd */
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 is outside of the set" },
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 { EBUSY, 0, "Set is in use, operation not permitted" },
359 for (i = 0; i < sizeof(table)/sizeof(struct translate_error); i++) {
360 if ((table[i].cmd == cmd || table[i].cmd == 0)
361 && table[i].err == err)
362 exit_error(err == EPROTO ? VERSION_PROBLEM
366 exit_error(OTHER_PROBLEM, "Error from kernel: %s", strerror(err));
369 static inline int wrapped_getsockopt(void *data, socklen_t *size)
372 int sockfd = kernel_getsocket();
375 res = getsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
377 && errno == ENOPROTOOPT
378 && ipset_insmod("ip_set", "/sbin/modprobe") == 0)
379 res = getsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
380 DP("res=%d errno=%d", res, errno);
385 static inline int wrapped_setsockopt(void *data, socklen_t size)
388 int sockfd = kernel_getsocket();
391 res = setsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
393 && errno == ENOPROTOOPT
394 && ipset_insmod("ip_set", "/sbin/modprobe") == 0)
395 res = setsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
396 DP("res=%d errno=%d", res, errno);
401 static void kernel_getfrom(unsigned cmd, void *data, socklen_t * size)
403 int res = wrapped_getsockopt(data, size);
406 kernel_error(cmd, errno);
409 static int kernel_sendto_handleerrno(unsigned cmd, unsigned op,
410 void *data, socklen_t size)
412 int res = wrapped_setsockopt(data, size);
418 kernel_error(cmd, errno);
421 return 0; /* all ok */
424 static void kernel_sendto(unsigned cmd, void *data, size_t size)
426 int res = wrapped_setsockopt(data, size);
429 kernel_error(cmd, errno);
432 static int kernel_getfrom_handleerrno(unsigned cmd, void *data, size_t * size)
434 int res = wrapped_getsockopt(data, size);
440 kernel_error(cmd, errno);
443 return 0; /* all ok */
446 static void check_protocolversion(void)
448 struct ip_set_req_version req_version;
449 socklen_t size = sizeof(struct ip_set_req_version);
450 int sockfd = kernel_getsocket();
453 req_version.op = IP_SET_OP_VERSION;
454 res = getsockopt(sockfd, SOL_IP, SO_IP_SET, &req_version, &size);
457 ipset_printf("I'm of protocol version %u.\n"
458 "Kernel module is not loaded in, "
459 "cannot verify kernel version.",
460 IP_SET_PROTOCOL_VERSION);
463 if (req_version.version != IP_SET_PROTOCOL_VERSION)
464 exit_error(OTHER_PROBLEM,
465 "Kernel ipset code is of protocol version %u."
466 "I'm of protocol version %u.\n"
467 "Please upgrade your kernel and/or ipset(8) utillity.",
468 req_version.version, IP_SET_PROTOCOL_VERSION);
471 static void set_command(unsigned *cmd, const int newcmd)
473 if (*cmd != CMD_NONE)
474 exit_error(PARAMETER_PROBLEM, "Can't use -%c with -%c\n",
475 cmd2char(*cmd), cmd2char(newcmd));
479 static void add_option(unsigned int *options, unsigned int option)
481 if (*options & option)
482 exit_error(PARAMETER_PROBLEM,
483 "multiple -%c flags not allowed",
488 void *ipset_malloc(size_t size)
495 if ((p = malloc(size)) == NULL) {
496 perror("ipset: not enough memory");
502 char *ipset_strdup(const char *s)
506 if ((p = strdup(s)) == NULL) {
507 perror("ipset: not enough memory");
513 void ipset_free(void **data)
522 static struct option *merge_options(struct option *oldopts,
523 const struct option *newopts,
524 unsigned int *option_offset)
526 unsigned int num_old, num_new, i;
527 struct option *merge;
529 for (num_old = 0; oldopts[num_old].name; num_old++);
530 for (num_new = 0; newopts[num_new].name; num_new++);
532 global_option_offset += OPTION_OFFSET;
533 *option_offset = global_option_offset;
535 merge = ipset_malloc(sizeof(struct option) * (num_new + num_old + 1));
536 memcpy(merge, oldopts, num_old * sizeof(struct option));
537 for (i = 0; i < num_new; i++) {
538 merge[num_old + i] = newopts[i];
539 merge[num_old + i].val += *option_offset;
541 memset(merge + num_old + num_new, 0, sizeof(struct option));
546 static char *ip_tohost(const struct in_addr *addr)
548 struct hostent *host;
550 if ((host = gethostbyaddr((char *) addr,
551 sizeof(struct in_addr),
553 DP("%s", host->h_name);
554 return (char *) host->h_name;
557 return (char *) NULL;
560 static char *ip_tonetwork(const struct in_addr *addr)
564 if ((net = getnetbyaddr((long) ntohl(addr->s_addr),
566 DP("%s", net->n_name);
567 return (char *) net->n_name;
570 return (char *) NULL;
573 /* Return a string representation of an IP address.
574 * Please notice that a pointer to static char* area is returned.
576 char *ip_tostring(ip_set_ip_t ip, unsigned options)
579 addr.s_addr = htonl(ip);
581 if (!(options & OPT_NUMERIC)) {
583 if ((name = ip_tohost(&addr)) != NULL ||
584 (name = ip_tonetwork(&addr)) != NULL)
588 return inet_ntoa(addr);
591 char *binding_ip_tostring(struct set *set, ip_set_ip_t ip, unsigned options)
593 return ip_tostring(ip, options);
595 char *ip_tostring_numeric(ip_set_ip_t ip)
597 return ip_tostring(ip, OPT_NUMERIC);
600 /* Fills the 'ip' with the parsed ip or host in host byte order */
601 void parse_ip(const char *str, ip_set_ip_t * ip)
603 struct hostent *host;
608 if (inet_aton(str, &addr) != 0) {
609 *ip = ntohl(addr.s_addr); /* We want host byte order */
613 host = gethostbyname(str);
615 if (host->h_addrtype != AF_INET ||
616 host->h_length != sizeof(struct in_addr))
617 exit_error(PARAMETER_PROBLEM,
618 "host/network `%s' not an internet name",
620 if (host->h_addr_list[1] != 0)
621 exit_error(PARAMETER_PROBLEM,
622 "host/network `%s' resolves to serveral ip-addresses. "
623 "Please specify one.", str);
625 *ip = ntohl(((struct in_addr *) host->h_addr_list[0])->s_addr);
629 exit_error(PARAMETER_PROBLEM, "host/network `%s' not found", str);
632 /* Fills 'mask' with the parsed mask in host byte order */
633 void parse_mask(const char *str, ip_set_ip_t * mask)
641 /* no mask at all defaults to 32 bits */
645 if (strchr(str, '.') && inet_aton(str, &addr) != 0) {
646 *mask = ntohl(addr.s_addr); /* We want host byte order */
649 if (sscanf(str, "%d", &bits) != 1 || bits < 0 || bits > 32)
650 exit_error(PARAMETER_PROBLEM,
651 "invalid mask `%s' specified", str);
653 DP("bits: %d", bits);
655 *mask = bits != 0 ? 0xFFFFFFFF << (32 - bits) : 0L;
658 /* Combines parse_ip and parse_mask */
660 parse_ipandmask(const char *str, ip_set_ip_t * ip, ip_set_ip_t * mask)
665 strncpy(buf, str, sizeof(buf) - 1);
668 if ((p = strrchr(buf, '/')) != NULL) {
670 parse_mask(p + 1, mask);
672 parse_mask(NULL, mask);
674 /* if a null mask is given, the name is ignored, like in "any/0" */
680 DP("%s ip: %08X (%s) mask: %08X",
681 str, *ip, ip_tostring_numeric(*ip), *mask);
683 /* Apply the netmask */
686 DP("%s ip: %08X (%s) mask: %08X",
687 str, *ip, ip_tostring_numeric(*ip), *mask);
690 /* Return a string representation of a port
691 * Please notice that a pointer to static char* area is returned
692 * and we assume TCP protocol.
694 char *port_tostring(ip_set_ip_t port, unsigned options)
696 struct servent *service;
697 static char name[] = "65535";
699 if (!(options & OPT_NUMERIC)) {
700 if ((service = getservbyport(htons(port), "tcp")))
701 return service->s_name;
703 sprintf(name, "%u", port);
708 string_to_number(const char *str, unsigned int min, unsigned int max,
714 /* Handle hex, octal, etc. */
716 number = strtol(str, &end, 0);
717 if (*end == '\0' && end != str) {
718 /* we parsed a number, let's see if we want this */
719 if (errno != ERANGE && min <= number && number <= max) {
728 string_to_port(const char *str, ip_set_ip_t *port)
730 struct servent *service;
732 if ((service = getservbyname(str, "tcp")) != NULL) {
733 *port = ntohs((unsigned short) service->s_port);
740 /* Fills the 'ip' with the parsed port in host byte order */
741 void parse_port(const char *str, ip_set_ip_t *port)
743 if ((string_to_number(str, 0, 65535, port) != 0)
744 && (string_to_port(str, port) != 0))
745 exit_error(PARAMETER_PROBLEM,
746 "Invalid TCP port `%s' specified", str);
752 static struct settype *settype_find(const char *typename)
754 struct settype *runner = all_settypes;
758 while (runner != NULL) {
759 if (strncmp(runner->typename, typename,
760 IP_SET_MAXNAMELEN) == 0)
763 runner = runner->next;
766 return NULL; /* not found */
769 static struct settype *settype_load(const char *typename)
771 char path[sizeof(IPSET_LIB_DIR) + sizeof(IPSET_LIB_NAME) +
773 struct settype *settype;
775 /* do some search in list */
776 settype = settype_find(typename);
778 return settype; /* found */
780 /* Else we have to load it */
781 sprintf(path, IPSET_LIB_DIR IPSET_LIB_NAME, typename);
783 if (dlopen(path, RTLD_NOW)) {
786 settype = settype_find(typename);
792 /* Can't load the settype */
793 exit_error(PARAMETER_PROBLEM,
794 "Couldn't load settype `%s':%s\n",
795 typename, dlerror());
797 return NULL; /* Never executed, but keep compilers happy */
800 static char *check_set_name(char *setname)
802 if (strlen(setname) > IP_SET_MAXNAMELEN - 1)
803 exit_error(PARAMETER_PROBLEM,
804 "Setname '%s' too long, max %d characters.",
805 setname, IP_SET_MAXNAMELEN - 1);
810 static struct settype *check_set_typename(const char *typename)
812 if (strlen(typename) > IP_SET_MAXNAMELEN - 1)
813 exit_error(PARAMETER_PROBLEM,
814 "Typename '%s' too long, max %d characters.",
815 typename, IP_SET_MAXNAMELEN - 1);
817 return settype_load(typename);
820 #define MAX(a,b) ((a) > (b) ? (a) : (b))
822 /* Register a new set type */
823 void settype_register(struct settype *settype)
828 DP("%s", settype->typename);
830 /* Check if this typename already exists */
831 chk = settype_find(settype->typename);
834 exit_error(OTHER_PROBLEM,
835 "Set type '%s' already registered!\n",
839 if (settype->protocol_version != IP_SET_PROTOCOL_VERSION)
840 exit_error(OTHER_PROBLEM,
841 "Set type %s is of wrong protocol version %u!"
842 " I'm of version %u.\n", settype->typename,
843 settype->protocol_version,
844 IP_SET_PROTOCOL_VERSION);
846 /* Initialize internal data */
847 settype->header = ipset_malloc(settype->header_size);
848 size = MAX(settype->create_size, settype->adt_size);
849 settype->data = ipset_malloc(size);
852 settype->next = all_settypes;
853 all_settypes = settype;
855 DP("%s registered", settype->typename);
858 /* Find set functions */
859 static struct set *set_find_byid(ip_set_id_t id)
861 struct set *set = NULL;
864 for (i = 0; i < max_sets; i++)
865 if (set_list[i] && set_list[i]->id == id) {
871 exit_error(PARAMETER_PROBLEM,
872 "Set identified by id %u is not found", id);
876 static struct set *set_find_byname(const char *name)
878 struct set *set = NULL;
881 for (i = 0; i < max_sets; i++)
883 && strncmp(set_list[i]->name, name,
884 IP_SET_MAXNAMELEN) == 0) {
889 exit_error(PARAMETER_PROBLEM,
890 "Set %s is not found", name);
894 static ip_set_id_t set_find_free_index(const char *name)
896 ip_set_id_t i, index = IP_SET_INVALID_ID;
898 for (i = 0; i < max_sets; i++) {
899 if (index == IP_SET_INVALID_ID
900 && set_list[i] == NULL)
902 if (set_list[i] != NULL
903 && strncmp(set_list[i]->name, name,
904 IP_SET_MAXNAMELEN) == 0)
905 exit_error(PARAMETER_PROBLEM,
906 "Set %s is already defined, cannot be restored",
910 if (index == IP_SET_INVALID_ID)
911 exit_error(PARAMETER_PROBLEM,
912 "Set %s cannot be restored, "
913 "max number of set %u reached",
920 * Send create set order to kernel
922 static void set_create(const char *name, struct settype *settype)
924 struct ip_set_req_create req_create;
928 DP("%s %s", name, settype->typename);
930 req_create.op = IP_SET_OP_CREATE;
931 req_create.version = IP_SET_PROTOCOL_VERSION;
932 strcpy(req_create.name, name);
933 strcpy(req_create.typename, settype->typename);
936 settype->create_final(settype->data, settype->flags);
938 /* Alloc memory for the data to send */
939 size = sizeof(struct ip_set_req_create) + settype->create_size;
940 data = ipset_malloc(size);
942 /* Add up ip_set_req_create and the settype data */
943 memcpy(data, &req_create, sizeof(struct ip_set_req_create));
944 memcpy(data + sizeof(struct ip_set_req_create),
945 settype->data, settype->create_size);
947 kernel_sendto(CMD_CREATE, data, size);
951 static void set_restore_create(const char *name, struct settype *settype)
955 DP("%s %s %u %u %u %u", name, settype->typename,
956 restore_offset, sizeof(struct ip_set_restore),
957 settype->create_size, restore_size);
959 /* Sanity checking */
961 + sizeof(struct ip_set_restore)
962 + settype->create_size > restore_size)
963 exit_error(PARAMETER_PROBLEM,
964 "Giving up, restore file is screwed up!");
967 settype->create_final(settype->data, settype->flags);
969 /* Fill out restore_data */
970 restore_set = (struct ip_set_restore *)
971 (restore_data + restore_offset);
972 strcpy(restore_set->name, name);
973 strcpy(restore_set->typename, settype->typename);
974 restore_set->index = set_find_free_index(name);
975 restore_set->header_size = settype->create_size;
976 restore_set->members_size = 0;
978 DP("name %s, restore index %u", restore_set->name, restore_set->index);
979 /* Add settype data */
981 memcpy(restore_data + restore_offset + sizeof(struct ip_set_restore),
982 settype->data, settype->create_size);
984 restore_offset += sizeof(struct ip_set_restore)
985 + settype->create_size;
987 /* Add set to set_list */
988 set = ipset_malloc(sizeof(struct set));
989 strcpy(set->name, name);
990 set->settype = settype;
991 set->index = restore_set->index;
992 set_list[restore_set->index] = set;
996 * Send destroy/flush order to kernel for one or all sets
998 static void set_destroy(const char *name, unsigned op, unsigned cmd)
1000 struct ip_set_req_std req;
1002 DP("%s %s", cmd == CMD_DESTROY ? "destroy" : "flush", name);
1005 req.version = IP_SET_PROTOCOL_VERSION;
1006 strcpy(req.name, name);
1008 kernel_sendto(cmd, &req, sizeof(struct ip_set_req_std));
1012 * Send rename/swap order to kernel
1014 static void set_rename(const char *name, const char *newname,
1015 unsigned op, unsigned cmd)
1017 struct ip_set_req_create req;
1019 DP("%s %s %s", cmd == CMD_RENAME ? "rename" : "swap",
1023 req.version = IP_SET_PROTOCOL_VERSION;
1024 strcpy(req.name, name);
1025 strcpy(req.typename, newname);
1027 kernel_sendto(cmd, &req,
1028 sizeof(struct ip_set_req_create));
1032 * Send MAX_SETS, LIST_SIZE and/or SAVE_SIZE orders to kernel
1034 static size_t load_set_list(const char name[IP_SET_MAXNAMELEN],
1036 unsigned op, unsigned cmd)
1039 struct ip_set_req_max_sets req_max_sets;
1040 struct ip_set_name_list *name_list;
1043 socklen_t size, req_size;
1044 int repeated = 0, res = 0;
1046 DP("%s %s", cmd == CMD_MAX_SETS ? "MAX_SETS"
1047 : cmd == CMD_LIST_SIZE ? "LIST_SIZE"
1053 for (i = 0; i < max_sets; i++)
1060 req_max_sets.op = IP_SET_OP_MAX_SETS;
1061 req_max_sets.version = IP_SET_PROTOCOL_VERSION;
1062 strcpy(req_max_sets.set.name, name);
1063 size = sizeof(req_max_sets);
1064 kernel_getfrom(CMD_MAX_SETS, &req_max_sets, &size);
1066 DP("got MAX_SETS: sets %d, max_sets %d",
1067 req_max_sets.sets, req_max_sets.max_sets);
1069 max_sets = req_max_sets.max_sets;
1070 set_list = ipset_malloc(max_sets * sizeof(struct set *));
1071 memset(set_list, 0, max_sets * sizeof(struct set *));
1072 *index = req_max_sets.set.index;
1074 if (req_max_sets.sets == 0)
1075 /* No sets in kernel */
1079 size = req_size = sizeof(struct ip_set_req_setnames)
1080 + req_max_sets.sets * sizeof(struct ip_set_name_list);
1081 data = ipset_malloc(size);
1082 ((struct ip_set_req_setnames *) data)->op = op;
1083 ((struct ip_set_req_setnames *) data)->index = *index;
1085 res = kernel_getfrom_handleerrno(cmd, data, &size);
1087 if (res != 0 || size != req_size) {
1089 if (repeated++ < LIST_TRIES)
1091 exit_error(OTHER_PROBLEM,
1092 "Tried to get sets from kernel %d times"
1093 " and failed. Please try again when the load on"
1094 " the sets has gone down.", LIST_TRIES);
1097 /* Load in setnames */
1098 size = sizeof(struct ip_set_req_setnames);
1099 while (size + sizeof(struct ip_set_name_list) <= req_size) {
1100 name_list = (struct ip_set_name_list *)
1102 set = ipset_malloc(sizeof(struct set));
1103 strcpy(set->name, name_list->name);
1104 set->index = name_list->index;
1105 set->id = name_list->id;
1106 set->settype = settype_load(name_list->typename);
1107 set_list[name_list->index] = set;
1108 DP("loaded %s, type %s, index %u",
1109 set->name, set->settype->typename, set->index);
1110 size += sizeof(struct ip_set_name_list);
1112 /* Size to get set members, bindings */
1113 size = ((struct ip_set_req_setnames *)data)->size;
1122 static size_t save_bindings(void *data, size_t offset, size_t len)
1124 struct ip_set_hash_save *hash =
1125 (struct ip_set_hash_save *) (data + offset);
1128 DP("offset %u, len %u", offset, len);
1129 if (offset + sizeof(struct ip_set_hash_save) > len)
1130 exit_error(OTHER_PROBLEM,
1131 "Save operation failed, try again later.");
1133 set = set_find_byid(hash->id);
1134 if (!(set && set_list[hash->binding]))
1135 exit_error(OTHER_PROBLEM,
1136 "Save binding failed, try again later.");
1137 printf("-B %s %s -b %s\n",
1139 set->settype->bindip_tostring(set, hash->ip, OPT_NUMERIC),
1140 set_list[hash->binding]->name);
1142 return sizeof(struct ip_set_hash_save);
1145 static size_t save_set(void *data, int *bindings,
1146 size_t offset, size_t len)
1148 struct ip_set_save *set_save =
1149 (struct ip_set_save *) (data + offset);
1151 struct settype *settype;
1154 DP("offset %u (%u/%u/%u), len %u", offset,
1155 sizeof(struct ip_set_save),
1156 set_save->header_size, set_save->members_size,
1158 if (offset + sizeof(struct ip_set_save) > len
1159 || offset + sizeof(struct ip_set_save)
1160 + set_save->header_size + set_save->members_size > len)
1161 exit_error(OTHER_PROBLEM,
1162 "Save operation failed, try again later.");
1164 DP("index: %u", set_save->index);
1165 if (set_save->index == IP_SET_INVALID_ID) {
1168 return sizeof(struct ip_set_save);
1170 set = set_list[set_save->index];
1172 exit_error(OTHER_PROBLEM,
1173 "Save set failed, try again later.");
1174 settype = set->settype;
1176 /* Init set header */
1177 used = sizeof(struct ip_set_save);
1178 settype->initheader(set, data + offset + used);
1180 /* Print create set */
1181 settype->saveheader(set, OPT_NUMERIC);
1184 used += set_save->header_size;
1185 settype->saveips(set, data + offset + used,
1186 set_save->members_size, OPT_NUMERIC);
1188 return (used + set_save->members_size);
1191 static size_t save_default_bindings(void *data, int *bindings)
1193 struct ip_set_save *set_save = (struct ip_set_save *) data;
1196 if (set_save->index == IP_SET_INVALID_ID) {
1199 return sizeof(struct ip_set_save);
1202 set = set_list[set_save->index];
1203 DP("%s, binding %u", set->name, set_save->binding);
1204 if (set_save->binding != IP_SET_INVALID_ID) {
1205 if (!set_list[set_save->binding])
1206 exit_error(OTHER_PROBLEM,
1207 "Save set failed, try again later.");
1209 printf("-B %s %s -b %s\n",
1210 set->name, IPSET_TOKEN_DEFAULT,
1211 set_list[set_save->binding]->name);
1213 return (sizeof(struct ip_set_save)
1214 + set_save->header_size
1215 + set_save->members_size);
1218 static int try_save_sets(const char name[IP_SET_MAXNAMELEN])
1221 socklen_t size, req_size = 0;
1223 int res = 0, bindings = 0;
1224 time_t now = time(NULL);
1226 /* Load set_list from kernel */
1227 size = load_set_list(name, &index,
1228 IP_SET_OP_SAVE_SIZE, CMD_SAVE);
1231 /* Get sets, bindings and print them */
1232 /* Take into account marker */
1233 req_size = (size += sizeof(struct ip_set_save));
1234 data = ipset_malloc(size);
1235 ((struct ip_set_req_list *) data)->op = IP_SET_OP_SAVE;
1236 ((struct ip_set_req_list *) data)->index = index;
1237 res = kernel_getfrom_handleerrno(CMD_SAVE, data, &size);
1239 if (res != 0 || size != req_size) {
1245 printf("# Generated by ipset %s on %s", IPSET_VERSION, ctime(&now));
1247 while (size < req_size) {
1248 DP("size: %u, req_size: %u", size, req_size);
1250 size += save_bindings(data, size, req_size);
1252 size += save_set(data, &bindings, size, req_size);
1254 /* Re-read data to save default bindings */
1257 while (size < req_size && bindings == 0)
1258 size += save_default_bindings(data + size, &bindings);
1262 printf("# Completed on %s", ctime(&now));
1268 * Performs a save to stdout
1270 static void set_save(const char name[IP_SET_MAXNAMELEN])
1275 for (i = 0; i < LIST_TRIES; i++)
1276 if (try_save_sets(name) == 0)
1279 if (errno == EAGAIN)
1280 exit_error(OTHER_PROBLEM,
1281 "Tried to save sets from kernel %d times"
1282 " and failed. Please try again when the load on"
1283 " the sets has gone down.", LIST_TRIES);
1285 kernel_error(CMD_SAVE, errno);
1292 /* global new argv and argc */
1293 static char *newargv[255];
1294 static int newargc = 0;
1296 /* Build faked argv from parsed line */
1297 static void build_argv(int line, char *buffer) {
1302 for (i = 1; i < newargc; i++)
1306 ptr = strtok(buffer, " \t\n");
1307 newargv[newargc++] = ipset_strdup(ptr);
1308 while ((ptr = strtok(NULL, " \t\n")) != NULL) {
1309 if ((newargc + 1) < sizeof(newargv)/sizeof(char *))
1310 newargv[newargc++] = ipset_strdup(ptr);
1312 exit_error(PARAMETER_PROBLEM,
1313 "Line %d is too long to restore\n", line);
1317 static FILE *create_tempfile(void)
1320 char *tmpdir = NULL;
1325 if (!(tmpdir = getenv("TMPDIR")) && !(tmpdir = getenv("TMP")))
1327 filename = ipset_malloc(strlen(tmpdir) + strlen(TEMPFILE_PATTERN) + 1);
1328 strcpy(filename, tmpdir);
1329 strcat(filename, TEMPFILE_PATTERN);
1331 (void) umask(077); /* Create with restrictive permissions */
1332 fd = mkstemp(filename);
1334 exit_error(OTHER_PROBLEM, "Could not create temporary file.");
1335 if (!(file = fdopen(fd, "r+")))
1336 exit_error(OTHER_PROBLEM, "Could not open temporary file.");
1337 if (unlink(filename) == -1)
1338 exit_error(OTHER_PROBLEM, "Could not unlink temporary file.");
1341 while (fgets(buffer, sizeof(buffer), stdin)) {
1342 fputs(buffer, file);
1344 fseek(file, 0L, SEEK_SET);
1350 * Performs a restore from a file
1352 static void set_restore(char *argv0)
1355 char *ptr, *name = NULL;
1357 int line = 0, first_pass, i, bindings = 0;
1358 struct settype *settype = NULL;
1359 struct ip_set_req_setnames *header;
1364 /* Create and store stdin in temporary file */
1365 in = create_tempfile();
1367 /* Load existing sets from kernel */
1368 load_set_list(IPSET_TOKEN_ALL, &index,
1369 IP_SET_OP_LIST_SIZE, CMD_RESTORE);
1371 restore_size = sizeof(struct ip_set_req_setnames)/* header */
1372 + sizeof(struct ip_set_restore); /* marker */
1373 DP("restore_size: %u", restore_size);
1374 /* First pass: calculate required amount of data */
1375 while (fgets(buffer, sizeof(buffer), in)) {
1378 if (buffer[0] == '\n')
1380 else if (buffer[0] == '#')
1382 else if (strcmp(buffer, "COMMIT\n") == 0) {
1383 /* Enable restore mode */
1389 ptr = strtok(buffer, " \t\n");
1396 || ptr[2] != '\0') {
1397 exit_error(PARAMETER_PROBLEM,
1398 "Line %u does not start as a valid restore command\n",
1403 ptr = strtok(NULL, " \t\n");
1404 DP("setname: %s", ptr);
1406 exit_error(PARAMETER_PROBLEM,
1407 "Missing set name in line %u\n",
1412 name = check_set_name(ptr);
1414 ptr = strtok(NULL, " \t\n");
1416 exit_error(PARAMETER_PROBLEM,
1417 "Missing settype in line %u\n",
1420 exit_error(PARAMETER_PROBLEM,
1421 "Invalid line %u: create must precede bindings\n",
1423 settype = check_set_typename(ptr);
1424 restore_size += sizeof(struct ip_set_restore)
1425 + settype->create_size;
1426 DP("restore_size (N): %u", restore_size);
1431 || strncmp(name, ptr, sizeof(name)) != 0)
1432 exit_error(PARAMETER_PROBLEM,
1433 "Add IP to set %s in line %u without "
1434 "preceding corresponding create set line\n",
1437 exit_error(PARAMETER_PROBLEM,
1438 "Invalid line %u: adding entries must precede bindings\n",
1440 restore_size += settype->adt_size;
1441 DP("restore_size (A): %u", restore_size);
1446 restore_size += sizeof(struct ip_set_hash_save);
1447 DP("restore_size (B): %u", restore_size);
1451 exit_error(PARAMETER_PROBLEM,
1452 "Unrecognized restore command in line %u\n",
1455 } /* end of switch */
1457 /* Sanity checking */
1459 exit_error(PARAMETER_PROBLEM,
1460 "Missing COMMIT line\n");
1461 DP("restore_size: %u", restore_size);
1462 restore_data = ipset_malloc(restore_size);
1463 header = (struct ip_set_req_setnames *) restore_data;
1464 header->op = IP_SET_OP_RESTORE;
1465 header->size = restore_size;
1466 restore_offset = sizeof(struct ip_set_req_setnames);
1468 /* Rewind to scan the file again */
1469 fseek(in, 0L, SEEK_SET);
1473 /* Initialize newargv/newargc */
1474 newargv[newargc++] = ipset_strdup(argv0);
1476 /* Second pass: build up restore request */
1477 while (fgets(buffer, sizeof(buffer), in)) {
1480 if (buffer[0] == '\n')
1482 else if (buffer[0] == '#')
1484 else if (strcmp(buffer, "COMMIT\n") == 0)
1486 DP("restoring: %s", buffer);
1487 /* Build faked argv, argc */
1488 build_argv(line, buffer);
1489 for (i = 0; i < newargc; i++)
1490 DP("argv[%u]: %s", i, newargv[i]);
1493 parse_commandline(newargc, newargv);
1495 exit_error(PARAMETER_PROBLEM,
1496 "Broken restore file\n");
1500 (restore_offset + sizeof(struct ip_set_restore))) {
1502 struct ip_set_restore *marker =
1503 (struct ip_set_restore *) (restore_data + restore_offset);
1505 DP("restore marker");
1506 marker->index = IP_SET_INVALID_ID;
1507 marker->header_size = marker->members_size = 0;
1508 restore_offset += sizeof(struct ip_set_restore);
1510 if (restore_size != restore_offset)
1511 exit_error(PARAMETER_PROBLEM,
1512 "Giving up, restore file is screwed up!");
1513 res = kernel_getfrom_handleerrno(CMD_RESTORE, restore_data, &restore_size);
1516 if (restore_size != sizeof(struct ip_set_req_setnames))
1517 exit_error(PARAMETER_PROBLEM,
1518 "Communication with kernel failed (%u %u)!",
1519 restore_size, sizeof(struct ip_set_req_setnames));
1521 header = (struct ip_set_req_setnames *) restore_data;
1522 if (header->size != 0)
1523 exit_error(PARAMETER_PROBLEM,
1524 "Committing restoring failed at line %u!",
1530 * Send ADT_GET order to kernel for a set
1532 static struct set *set_adt_get(const char *name)
1534 struct ip_set_req_adt_get req_adt_get;
1540 req_adt_get.op = IP_SET_OP_ADT_GET;
1541 req_adt_get.version = IP_SET_PROTOCOL_VERSION;
1542 strcpy(req_adt_get.set.name, name);
1543 size = sizeof(struct ip_set_req_adt_get);
1545 kernel_getfrom(CMD_ADT_GET, (void *) &req_adt_get, &size);
1547 set = ipset_malloc(sizeof(struct set));
1548 strcpy(set->name, name);
1549 set->index = req_adt_get.set.index;
1550 set->settype = settype_load(req_adt_get.typename);
1556 * Send add/del/test order to kernel for a set
1558 static int set_adtip(struct set *set, const char *adt,
1559 unsigned op, unsigned cmd)
1561 struct ip_set_req_adt *req_adt;
1566 DP("%s -> %s", set->name, adt);
1568 /* Alloc memory for the data to send */
1569 size = sizeof(struct ip_set_req_adt) + set->settype->adt_size ;
1570 DP("alloc size %i", size);
1571 data = ipset_malloc(size);
1573 /* Fill out the request */
1574 req_adt = (struct ip_set_req_adt *) data;
1576 req_adt->index = set->index;
1577 memcpy(data + sizeof(struct ip_set_req_adt),
1578 set->settype->data, set->settype->adt_size);
1580 if (kernel_sendto_handleerrno(cmd, op, data, size) == -1)
1582 case IP_SET_OP_ADD_IP:
1583 exit_error(OTHER_PROBLEM, "%s is already in set %s.",
1586 case IP_SET_OP_DEL_IP:
1587 exit_error(OTHER_PROBLEM, "%s is not in set %s.",
1590 case IP_SET_OP_TEST_IP:
1591 ipset_printf("%s is in set %s.", adt, set->name);
1599 case IP_SET_OP_TEST_IP:
1600 ipset_printf("%s is NOT in set %s.", adt, set->name);
1611 static void set_restore_add(struct set *set, const char *adt)
1613 DP("%s %s", set->name, adt);
1614 /* Sanity checking */
1615 if (restore_offset + set->settype->adt_size > restore_size)
1616 exit_error(PARAMETER_PROBLEM,
1617 "Giving up, restore file is screwed up!");
1619 memcpy(restore_data + restore_offset,
1620 set->settype->data, set->settype->adt_size);
1621 restore_set->members_size += set->settype->adt_size;
1622 restore_offset += set->settype->adt_size;
1626 * Send bind/unbind/test binding order to kernel for a set
1628 static int set_bind(struct set *set, const char *adt,
1629 const char *binding,
1630 unsigned op, unsigned cmd)
1632 struct ip_set_req_bind *req_bind;
1637 /* set may be null: '-U :all: :all:|:default:' */
1638 DP("(%s, %s) -> %s", set ? set->name : IPSET_TOKEN_ALL, adt, binding);
1641 if (strcmp(set->settype->typename, "iptreemap") == 0)
1642 exit_error(PARAMETER_PROBLEM,
1643 "iptreemap type of sets cannot be used at binding operations\n");
1644 /* Alloc memory for the data to send */
1645 size = sizeof(struct ip_set_req_bind);
1646 if (op != IP_SET_OP_UNBIND_SET && adt[0] == ':')
1647 /* Set default binding */
1648 size += IP_SET_MAXNAMELEN;
1649 else if (!(op == IP_SET_OP_UNBIND_SET && set == NULL))
1650 size += set->settype->adt_size;
1651 DP("alloc size %i", size);
1652 data = ipset_malloc(size);
1654 /* Fill out the request */
1655 req_bind = (struct ip_set_req_bind *) data;
1657 req_bind->index = set ? set->index : IP_SET_INVALID_ID;
1658 if (adt[0] == ':') {
1659 /* ':default:' and ':all:' */
1660 strncpy(req_bind->binding, adt, IP_SET_MAXNAMELEN);
1661 if (op != IP_SET_OP_UNBIND_SET && adt[0] == ':')
1662 strncpy(data + sizeof(struct ip_set_req_bind),
1663 binding, IP_SET_MAXNAMELEN);
1665 strncpy(req_bind->binding, binding, IP_SET_MAXNAMELEN);
1666 memcpy(data + sizeof(struct ip_set_req_bind),
1667 set->settype->data, set->settype->adt_size);
1670 if (op == IP_SET_OP_TEST_BIND_SET) {
1671 if (kernel_sendto_handleerrno(cmd, op, data, size) == -1) {
1672 ipset_printf("%s in set %s is bound to %s.",
1673 adt, set->name, binding);
1676 ipset_printf("%s in set %s is NOT bound to %s.",
1677 adt, set->name, binding);
1681 kernel_sendto(cmd, data, size);
1687 static void set_restore_bind(struct set *set,
1689 const char *binding)
1691 struct ip_set_hash_save *hash_restore;
1695 struct ip_set_restore *marker =
1696 (struct ip_set_restore *) (restore_data + restore_offset);
1698 DP("restore marker");
1699 if (restore_offset + sizeof(struct ip_set_restore)
1701 exit_error(PARAMETER_PROBLEM,
1702 "Giving up, restore file is screwed up!");
1703 marker->index = IP_SET_INVALID_ID;
1704 marker->header_size = marker->members_size = 0;
1705 restore_offset += sizeof(struct ip_set_restore);
1708 /* Sanity checking */
1709 if (restore_offset + sizeof(struct ip_set_hash_save) > restore_size)
1710 exit_error(PARAMETER_PROBLEM,
1711 "Giving up, restore file is screwed up!");
1713 hash_restore = (struct ip_set_hash_save *) (restore_data + restore_offset);
1714 DP("%s -> %s", adt, binding);
1715 if (strcmp(adt, IPSET_TOKEN_DEFAULT) == 0)
1716 hash_restore->ip = 0;
1718 set->settype->bindip_parse(adt, &hash_restore->ip);
1719 hash_restore->id = set->index;
1720 hash_restore->binding = (set_find_byname(binding))->index;
1721 DP("id %u, ip %u, binding %u",
1722 hash_restore->id, hash_restore->ip, hash_restore->binding);
1723 restore_offset += sizeof(struct ip_set_hash_save);
1730 static void print_bindings(struct set *set,
1731 void *data, size_t size, unsigned options,
1732 char * (*printip)(struct set *set,
1733 ip_set_ip_t ip, unsigned options))
1736 struct ip_set_hash_list *hash;
1738 while (offset < size) {
1739 hash = (struct ip_set_hash_list *) (data + offset);
1740 printf("%s -> %s\n",
1741 printip(set, hash->ip, options),
1742 set_list[hash->binding]->name);
1743 offset += sizeof(struct ip_set_hash_list);
1747 /* Help function to set_list() */
1748 static size_t print_set(void *data, unsigned options)
1750 struct ip_set_list *setlist = (struct ip_set_list *) data;
1751 struct set *set = set_list[setlist->index];
1752 struct settype *settype = set->settype;
1755 /* Pretty print the set */
1756 printf("Name: %s\n", set->name);
1757 printf("Type: %s\n", settype->typename);
1758 printf("References: %d\n", setlist->ref);
1759 printf("Default binding: %s\n",
1760 setlist->binding == IP_SET_INVALID_ID ? ""
1761 : set_list[setlist->binding]->name);
1764 offset = sizeof(struct ip_set_list);
1765 settype->initheader(set, data + offset);
1767 /* Pretty print the type header */
1769 settype->printheader(set, options);
1771 /* Pretty print all IPs */
1772 printf("Members:\n");
1773 offset += setlist->header_size;
1774 if (options & OPT_SORTED)
1775 settype->printips_sorted(set, data + offset,
1776 setlist->members_size, options);
1778 settype->printips(set, data + offset,
1779 setlist->members_size, options);
1781 /* Print bindings */
1782 printf("Bindings:\n");
1783 offset += setlist->members_size;
1785 data + offset, setlist->bindings_size, options,
1786 settype->bindip_tostring);
1788 printf("\n"); /* One newline between sets */
1790 return (offset + setlist->bindings_size);
1793 static int try_list_sets(const char name[IP_SET_MAXNAMELEN],
1798 socklen_t size, req_size;
1802 /* Load set_list from kernel */
1803 size = req_size = load_set_list(name, &index,
1804 IP_SET_OP_LIST_SIZE, CMD_LIST);
1807 /* Get sets and print them */
1808 data = ipset_malloc(size);
1809 ((struct ip_set_req_list *) data)->op = IP_SET_OP_LIST;
1810 ((struct ip_set_req_list *) data)->index = index;
1811 res = kernel_getfrom_handleerrno(CMD_LIST, data, &size);
1812 DP("get_lists getsockopt() res=%d errno=%d", res, errno);
1814 if (res != 0 || size != req_size) {
1820 while (size != req_size)
1821 size += print_set(data + size, options);
1827 /* Print a set or all sets
1828 * All sets: name = NULL
1830 static void list_sets(const char name[IP_SET_MAXNAMELEN], unsigned options)
1835 for (i = 0; i < LIST_TRIES; i++)
1836 if (try_list_sets(name, options) == 0)
1839 if (errno == EAGAIN)
1840 exit_error(OTHER_PROBLEM,
1841 "Tried to list sets from kernel %d times"
1842 " and failed. Please try again when the load on"
1843 " the sets has gone down.", LIST_TRIES);
1845 kernel_error(CMD_LIST, errno);
1849 * If settype is non null help for that type is printed as well
1851 static void set_help(const struct settype *settype)
1855 " --debug -z Enable debugging\n\n";
1857 char debughelp[] = "\n";
1861 "Usage: %s -N new-set settype [options]\n"
1862 " %s -[XFLSH] [set] [options]\n"
1863 " %s -[EW] from-set to-set\n"
1864 " %s -[ADTU] set IP\n"
1865 " %s -B set IP option\n"
1867 " %s -h (print this help information)\n\n",
1868 program_name, program_version,
1869 program_name, program_name, program_name,
1870 program_name, program_name, program_name,
1873 printf("Commands:\n"
1874 "Either long or short options are allowed.\n"
1875 " --create -N setname settype <options>\n"
1876 " Create a new set\n"
1877 " --destroy -X [setname]\n"
1878 " Destroy a set or all sets\n"
1879 " --flush -F [setname]\n"
1880 " Flush a set or all sets\n"
1881 " --rename -E from-set to-set\n"
1882 " Rename from-set to to-set\n"
1883 " --swap -W from-set to-set\n"
1884 " Swap the content of two existing sets\n"
1885 " --list -L [setname] [options]\n"
1886 " List the IPs in a set or all sets\n"
1887 " --save -S [setname]\n"
1888 " Save the set or all sets to stdout\n"
1889 " --restore -R [option]\n"
1890 " Restores a saved state\n"
1891 " --add -A setname IP\n"
1892 " Add an IP to a set\n"
1893 " --del -D setname IP\n"
1894 " Deletes an IP from a set\n"
1895 " --test -T setname IP \n"
1896 " Tests if an IP exists in a set.\n"
1897 " --bind -B setname IP|:default: -b bind-setname\n"
1898 " Bind the IP in setname to bind-setname.\n"
1899 " --unbind -U setname IP|:all:|:default:\n"
1900 " Delete binding belonging to IP,\n"
1901 " all bindings or default binding of setname.\n"
1902 " --unbind -U :all: :all:|:default:\n"
1903 " Delete all bindings or all default bindings.\n"
1904 " --help -H [settype]\n"
1905 " Prints this help, and settype specific help\n"
1907 " Prints version information\n\n"
1909 " --sorted -s Numeric sort of the IPs in -L\n"
1910 " --numeric -n Numeric output of addresses in a -L\n"
1911 " --quiet -q Suppress any output to stdout and stderr.\n"
1912 " --binding -b Specifies the binding for -B\n");
1915 if (settype != NULL) {
1916 printf("Type '%s' specific:\n", settype->typename);
1921 static int find_cmd(const char option)
1925 for (i = 1; i <= NUMBER_OF_CMD; i++)
1926 if (cmdflags[i] == option)
1932 static int parse_adt_cmdline(unsigned command,
1936 struct settype **settype)
1940 /* -U :all: :all:|:default: */
1941 if (command == CMD_UNBIND) {
1942 if (strcmp(name, IPSET_TOKEN_ALL) == 0) {
1943 if (strcmp(adt, IPSET_TOKEN_DEFAULT) == 0
1944 || strcmp(adt, IPSET_TOKEN_ALL) == 0) {
1949 exit_error(PARAMETER_PROBLEM,
1950 "-U %s requires %s or %s as binding name",
1952 IPSET_TOKEN_DEFAULT,
1956 *set = restore ? set_find_byname(name)
1957 : set_adt_get(name);
1959 /* Reset space for adt data */
1960 *settype = (*set)->settype;
1961 memset((*settype)->data, 0, (*settype)->adt_size);
1963 if ((command == CMD_TEST
1964 || command == CMD_BIND
1965 || command == CMD_UNBIND)
1966 && (strcmp(adt, IPSET_TOKEN_DEFAULT) == 0
1967 || strcmp(adt, IPSET_TOKEN_ALL) == 0))
1970 res = (*settype)->adt_parser(
1978 /* Main worker function */
1979 int parse_commandline(int argc, char *argv[])
1982 unsigned command = CMD_NONE;
1983 unsigned options = 0;
1986 char *name = NULL; /* All except -H, -R */
1987 char *newname = NULL; /* -E, -W */
1988 char *adt = NULL; /* -A, -D, -T, -B, -U */
1989 char *binding = NULL; /* -B */
1990 struct set *set = NULL; /* -A, -D, -T, -B, -U */
1991 struct settype *settype = NULL; /* -N, -H */
1992 char all_sets[] = IPSET_TOKEN_ALL;
1994 struct option *opts = opts_long;
1996 /* Suppress error messages: we may add new options if we
1997 demand-load a protocol. */
1999 /* Reset optind to 0 for restore */
2002 while ((c = getopt_long(argc, argv, opts_short, opts, NULL)) != -1) {
2004 DP("commandline parsed: opt %c (%s)", c, argv[optind]);
2011 case 'H':{ /* Help: -H [typename [options]] */
2012 check_protocolversion();
2013 set_command(&command, CMD_HELP);
2016 settype = check_set_typename(optarg);
2017 else if (optind < argc
2018 && argv[optind][0] != '-')
2019 settype = check_set_typename(argv[optind++]);
2024 case 'V':{ /* Version */
2025 printf("%s v%s Protocol version %u.\n",
2026 program_name, program_version,
2027 IP_SET_PROTOCOL_VERSION);
2028 check_protocolversion();
2032 case 'N':{ /* Create: -N name typename options */
2033 set_command(&command, CMD_CREATE);
2035 name = check_set_name(optarg);
2037 /* Protect reserved names (binding) */
2039 exit_error(PARAMETER_PROBLEM,
2040 "setname might not start with colon",
2041 cmd2char(CMD_CREATE));
2044 && argv[optind][0] != '-')
2045 settype = check_set_typename(argv[optind++]);
2047 exit_error(PARAMETER_PROBLEM,
2048 "-%c requires setname and settype",
2049 cmd2char(CMD_CREATE));
2051 DP("merge options");
2052 /* Merge the create options */
2053 opts = merge_options(opts,
2054 settype->create_opts,
2055 &settype->option_offset);
2057 /* Reset space for create data */
2058 memset(settype->data, 0, settype->create_size);
2060 /* Zero the flags */
2063 DP("call create_init");
2064 /* Call the settype create_init */
2065 settype->create_init(settype->data);
2070 case 'X': /* Destroy */
2071 case 'F': /* Flush */
2072 case 'L': /* List */
2073 case 'S':{ /* Save */
2074 set_command(&command, find_cmd(c));
2077 name = check_set_name(optarg);
2078 else if (optind < argc
2079 && argv[optind][0] != '-')
2080 name = check_set_name(argv[optind++]);
2087 case 'R':{ /* Restore */
2088 set_command(&command, find_cmd(c));
2093 case 'E': /* Rename */
2094 case 'W':{ /* Swap */
2095 set_command(&command, find_cmd(c));
2096 name = check_set_name(optarg);
2099 && argv[optind][0] != '-')
2100 newname = check_set_name(argv[optind++]);
2102 exit_error(PARAMETER_PROBLEM,
2103 "-%c requires a setname "
2104 "and the new name for that set",
2105 cmd2char(CMD_RENAME));
2110 case 'A': /* Add IP */
2111 case 'D': /* Del IP */
2112 case 'T': /* Test IP */
2113 case 'B': /* Bind IP */
2114 case 'U':{ /* Unbind IP */
2115 set_command(&command, find_cmd(c));
2117 name = check_set_name(optarg);
2121 && argv[optind][0] != '-')
2122 adt = argv[optind++];
2124 exit_error(PARAMETER_PROBLEM,
2125 "-%c requires setname and IP",
2128 res = parse_adt_cmdline(command, name, adt,
2132 exit_error(PARAMETER_PROBLEM,
2143 add_option(&options, OPT_NUMERIC);
2147 add_option(&options, OPT_SORTED);
2151 add_option(&options, OPT_QUIET);
2156 case 'z': /* debug */
2157 add_option(&options, OPT_DEBUG);
2163 add_option(&options, OPT_BINDING);
2164 binding = check_set_name(optarg);
2167 case 1: /* non option */
2168 printf("Bad argument `%s'\n", optarg);
2170 break; /*always good */
2177 res = settype->create_parse(
2178 c - settype->option_offset,
2185 res = 0; /* failed */
2186 } /* switch (command) */
2190 exit_error(PARAMETER_PROBLEM,
2200 } /* while( getopt_long() ) */
2204 exit_error(PARAMETER_PROBLEM,
2205 "unknown arguments found on commandline");
2206 if (command == CMD_NONE)
2207 exit_error(PARAMETER_PROBLEM, "no command specified");
2210 generic_opt_check(command, options);
2212 DP("cmd: %c", cmd2char(command));
2218 set_restore_create(name, settype);
2220 set_create(name, settype);
2224 set_destroy(name, IP_SET_OP_DESTROY, CMD_DESTROY);
2228 set_destroy(name, IP_SET_OP_FLUSH, CMD_FLUSH);
2232 set_rename(name, newname, IP_SET_OP_RENAME, CMD_RENAME);
2236 set_rename(name, newname, IP_SET_OP_SWAP, CMD_SWAP);
2240 list_sets(name, options);
2248 set_restore(argv[0]);
2253 set_restore_add(set, adt);
2255 set_adtip(set, adt, IP_SET_OP_ADD_IP, CMD_ADD);
2259 set_adtip(set, adt, IP_SET_OP_DEL_IP, CMD_DEL);
2264 res = set_bind(set, adt, binding,
2265 IP_SET_OP_TEST_BIND_SET, CMD_TEST);
2267 res = set_adtip(set, adt,
2268 IP_SET_OP_TEST_IP, CMD_TEST);
2273 set_restore_bind(set, adt, binding);
2275 set_bind(set, adt, binding,
2276 IP_SET_OP_BIND_SET, CMD_BIND);
2280 set_bind(set, adt, "", IP_SET_OP_UNBIND_SET, CMD_UNBIND);
2288 /* Will never happen */
2289 break; /* Keep the compiler happy */
2291 } /* switch( command ) */
2297 int main(int argc, char *argv[])
2299 return parse_commandline(argc, argv);