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 #include <asm/bitops.h>
28 char program_name[] = "ipset";
29 char program_version[] = IPSET_VERSION;
31 /* The list of loaded set types */
32 static struct settype *all_settypes = NULL;
35 struct set **set_list = NULL;
36 ip_set_id_t max_sets = 0;
38 /* Suppress output to stdout and stderr? */
39 static int option_quiet = 0;
41 /* Data for restore mode */
42 static int restore = 0;
43 void *restore_data = NULL;
44 struct ip_set_restore *restore_set = NULL;
45 size_t restore_offset = 0, restore_size;
48 #define TEMPFILE_PATTERN "/ipsetXXXXXX"
54 #define OPTION_OFFSET 256
55 static unsigned int global_option_offset = 0;
57 /* Most of these command parsing functions are borrowed from iptables.c */
59 static const char cmdflags[] = { ' ', /* CMD_NONE */
60 'N', 'X', 'F', 'E', 'W', 'L', 'S', 'R',
61 'A', 'D', 'T', 'B', 'U', 'H', 'V',
65 #define OPT_NONE 0x0000U
66 #define OPT_NUMERIC 0x0001U /* -n */
67 #define OPT_SORTED 0x0002U /* -s */
68 #define OPT_QUIET 0x0004U /* -q */
69 #define OPT_DEBUG 0x0008U /* -z */
70 #define OPT_BINDING 0x0010U /* -b */
71 #define NUMBER_OF_OPT 5
72 static const char optflags[] =
73 { 'n', 's', 'q', 'z', 'b' };
75 static struct option opts_long[] = {
77 {"create", 1, 0, 'N'},
78 {"destroy", 2, 0, 'X'},
80 {"rename", 1, 0, 'E'},
85 {"restore", 0, 0, 'R'},
87 /* ip in set operations */
92 /* binding operations */
94 {"unbind", 1, 0, 'U'},
97 {"numeric", 0, 0, 'n'},
98 {"sorted", 0, 0, 's'},
100 {"binding", 1, 0, 'b'},
103 /* debug (if compiled with it) */
104 {"debug", 0, 0, 'z'},
107 /* version and help */
108 {"version", 0, 0, 'V'},
115 static char opts_short[] =
116 "-N:X::F::E:W:L::S::RA:D:T:B:U:nsqzb:Vh::H::";
118 /* Table of legal combinations of commands and options. If any of the
119 * given commands make an option legal, that option is legal.
126 static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] = {
128 /*CREATE*/ {'x', 'x', ' ', ' ', 'x'},
129 /*DESTROY*/ {'x', 'x', ' ', ' ', 'x'},
130 /*FLUSH*/ {'x', 'x', ' ', ' ', 'x'},
131 /*RENAME*/ {'x', 'x', ' ', ' ', 'x'},
132 /*SWAP*/ {'x', 'x', ' ', ' ', 'x'},
133 /*LIST*/ {' ', ' ', 'x', ' ', 'x'},
134 /*SAVE*/ {'x', 'x', ' ', ' ', 'x'},
135 /*RESTORE*/ {'x', 'x', ' ', ' ', 'x'},
136 /*ADD*/ {'x', 'x', ' ', ' ', 'x'},
137 /*DEL*/ {'x', 'x', ' ', ' ', 'x'},
138 /*TEST*/ {'x', 'x', ' ', ' ', ' '},
139 /*BIND*/ {'x', 'x', ' ', ' ', '+'},
140 /*UNBIND*/ {'x', 'x', ' ', ' ', 'x'},
141 /*HELP*/ {'x', 'x', 'x', ' ', 'x'},
142 /*VERSION*/ {'x', 'x', 'x', ' ', 'x'},
145 /* Main parser function */
146 int parse_commandline(int argc, char *argv[]);
148 void exit_tryhelp(int status)
151 "Try `%s -H' or '%s --help' for more information.\n",
152 program_name, program_name);
156 void exit_error(enum exittype status, char *msg, ...)
162 fprintf(stderr, "%s v%s: ", program_name, program_version);
163 vfprintf(stderr, msg, args);
165 fprintf(stderr, "\n");
167 fprintf(stderr, "Restore failed at line %u:\n", line);
168 if (status == PARAMETER_PROBLEM)
169 exit_tryhelp(status);
170 if (status == VERSION_PROBLEM)
172 "Perhaps %s or your kernel needs to be upgraded.\n",
179 void ipset_printf(char *msg, ...)
185 vfprintf(stdout, msg, args);
187 fprintf(stdout, "\n");
191 static void generic_opt_check(int command, int options)
195 /* Check that commands are valid with options. Complicated by the
196 * fact that if an option is legal with *any* command given, it is
197 * legal overall (ie. -z and -l).
199 for (i = 0; i < NUMBER_OF_OPT; i++) {
200 legal = 0; /* -1 => illegal, 1 => legal, 0 => undecided. */
202 for (j = 1; j <= NUMBER_OF_CMD; j++) {
206 if (!(options & (1 << i))) {
207 if (commands_v_options[j-1][i] == '+')
208 exit_error(PARAMETER_PROBLEM,
209 "You need to supply the `-%c' "
210 "option for this command\n",
213 if (commands_v_options[j-1][i] != 'x')
220 exit_error(PARAMETER_PROBLEM,
221 "Illegal option `-%c' with this command\n",
226 static char opt2char(int option)
229 for (ptr = optflags; option > 1; option >>= 1, ptr++);
234 static char cmd2char(int option)
236 if (option <= CMD_NONE || option > NUMBER_OF_CMD)
239 return cmdflags[option];
242 static int kernel_getsocket(void)
246 sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
248 exit_error(OTHER_PROBLEM,
249 "You need to be root to perform this command.");
254 static void kernel_error(unsigned cmd, int err)
257 struct translate_error {
262 { /* Generic error codes */
263 { EPERM, 0, "Missing capability" },
264 { EBADF, 0, "Invalid socket option" },
265 { EINVAL, 0, "Size mismatch for expected socket data" },
266 { ENOMEM, 0, "Not enough memory" },
267 { EFAULT, 0, "Failed to copy data" },
268 { EPROTO, 0, "ipset kernel/userspace version mismatch" },
269 { EBADMSG, 0, "Unknown command" },
270 /* Per command error codes */
271 /* Reserved ones for add/del/test to handle internally:
274 { ENOENT, CMD_CREATE, "Unknown set type" },
275 { ENOENT, 0, "Unknown set" },
276 { EAGAIN, 0, "Sets are busy, try again later" },
277 { ERANGE, CMD_CREATE, "No free slot remained to add a new set" },
278 { ERANGE, 0, "IP/port is outside of the set" },
279 { ENOEXEC, CMD_CREATE, "Invalid parameters to create a set" },
280 { ENOEXEC, CMD_SWAP, "Sets with different types cannot be swapped" },
281 { EEXIST, CMD_CREATE, "Set already exists" },
282 { EEXIST, CMD_RENAME, "Set with new name already exists" },
283 { EBUSY, 0, "Set is in use, operation not permitted" },
285 for (i = 0; i < sizeof(table)/sizeof(struct translate_error); i++) {
286 if ((table[i].cmd == cmd || table[i].cmd == 0)
287 && table[i].err == err)
288 exit_error(err == EPROTO ? VERSION_PROBLEM
292 exit_error(OTHER_PROBLEM, "Error from kernel: %s", strerror(err));
295 static void kernel_getfrom(unsigned cmd, void *data, size_t * size)
298 int sockfd = kernel_getsocket();
301 res = getsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
303 DP("res=%d errno=%d", res, errno);
306 kernel_error(cmd, errno);
309 static int kernel_sendto_handleerrno(unsigned cmd, unsigned op,
310 void *data, size_t size)
313 int sockfd = kernel_getsocket();
316 res = setsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
318 DP("res=%d errno=%d", res, errno);
324 kernel_error(cmd, errno);
327 return 0; /* all ok */
330 static void kernel_sendto(unsigned cmd, void *data, size_t size)
333 int sockfd = kernel_getsocket();
336 res = setsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
338 DP("res=%d errno=%d", res, errno);
341 kernel_error(cmd, errno);
344 static int kernel_getfrom_handleerrno(unsigned cmd, void *data, size_t * size)
347 int sockfd = kernel_getsocket();
350 res = getsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
352 DP("res=%d errno=%d", res, errno);
358 kernel_error(cmd, errno);
361 return 0; /* all ok */
364 static void check_protocolversion(void)
366 struct ip_set_req_version req_version;
367 size_t size = sizeof(struct ip_set_req_version);
368 int sockfd = kernel_getsocket();
371 req_version.op = IP_SET_OP_VERSION;
372 res = getsockopt(sockfd, SOL_IP, SO_IP_SET, &req_version, &size);
375 ipset_printf("I'm of protocol version %u.\n"
376 "Kernel module is not loaded in, "
377 "cannot verify kernel version.",
378 IP_SET_PROTOCOL_VERSION);
381 if (req_version.version != IP_SET_PROTOCOL_VERSION)
382 exit_error(OTHER_PROBLEM,
383 "Kernel ipset code is of protocol version %u."
384 "I'm of protocol version %u.\n"
385 "Please upgrade your kernel and/or ipset(8) utillity.",
386 req_version.version, IP_SET_PROTOCOL_VERSION);
389 static void set_command(int *cmd, const int newcmd)
391 if (*cmd != CMD_NONE)
392 exit_error(PARAMETER_PROBLEM, "Can't use -%c with -%c\n",
393 cmd2char(*cmd), cmd2char(newcmd));
397 static void add_option(unsigned int *options, unsigned int option)
399 if (*options & option)
400 exit_error(PARAMETER_PROBLEM,
401 "multiple -%c flags not allowed",
406 void *ipset_malloc(size_t size)
413 if ((p = malloc(size)) == NULL) {
414 perror("ipset: not enough memory");
420 char *ipset_strdup(const char *s)
424 if ((p = strdup(s)) == NULL) {
425 perror("ipset: not enough memory");
431 void ipset_free(void **data)
440 static struct option *merge_options(struct option *oldopts,
441 const struct option *newopts,
442 unsigned int *option_offset)
444 unsigned int num_old, num_new, i;
445 struct option *merge;
447 for (num_old = 0; oldopts[num_old].name; num_old++);
448 for (num_new = 0; newopts[num_new].name; num_new++);
450 global_option_offset += OPTION_OFFSET;
451 *option_offset = global_option_offset;
453 merge = ipset_malloc(sizeof(struct option) * (num_new + num_old + 1));
454 memcpy(merge, oldopts, num_old * sizeof(struct option));
455 for (i = 0; i < num_new; i++) {
456 merge[num_old + i] = newopts[i];
457 merge[num_old + i].val += *option_offset;
459 memset(merge + num_old + num_new, 0, sizeof(struct option));
464 static char *ip_tohost(const struct in_addr *addr)
466 struct hostent *host;
468 if ((host = gethostbyaddr((char *) addr,
469 sizeof(struct in_addr),
471 DP("%s", host->h_name);
472 return (char *) host->h_name;
475 return (char *) NULL;
478 static char *ip_tonetwork(const struct in_addr *addr)
482 if ((net = getnetbyaddr((long) ntohl(addr->s_addr),
484 DP("%s", net->n_name);
485 return (char *) net->n_name;
488 return (char *) NULL;
491 /* Return a string representation of an IP address.
492 * Please notice that a pointer to static char* area is returned.
494 char *ip_tostring(ip_set_ip_t ip, unsigned options)
497 addr.s_addr = htonl(ip);
499 if (!(options & OPT_NUMERIC)) {
501 if ((name = ip_tohost(&addr)) != NULL ||
502 (name = ip_tonetwork(&addr)) != NULL)
506 return inet_ntoa(addr);
509 char *binding_ip_tostring(struct set *set, ip_set_ip_t ip, unsigned options)
511 return ip_tostring(ip, options);
513 char *ip_tostring_numeric(ip_set_ip_t ip)
515 return ip_tostring(ip, OPT_NUMERIC);
518 /* Fills the 'ip' with the parsed ip or host in host byte order */
519 void parse_ip(const char *str, ip_set_ip_t * ip)
521 struct hostent *host;
526 if (inet_aton(str, &addr) != 0) {
527 *ip = ntohl(addr.s_addr); /* We want host byte order */
531 host = gethostbyname(str);
533 if (host->h_addrtype != AF_INET ||
534 host->h_length != sizeof(struct in_addr))
535 exit_error(PARAMETER_PROBLEM,
536 "host/network `%s' not an internet name",
538 if (host->h_addr_list[1] != 0)
539 exit_error(PARAMETER_PROBLEM,
540 "host/network `%s' resolves to serveral ip-addresses. "
541 "Please specify one.", str);
543 *ip = ntohl(((struct in_addr *) host->h_addr_list[0])->s_addr);
547 exit_error(PARAMETER_PROBLEM, "host/network `%s' not found", str);
550 /* Fills 'mask' with the parsed mask in host byte order */
551 void parse_mask(const char *str, ip_set_ip_t * mask)
559 /* no mask at all defaults to 32 bits */
563 if (strchr(str, '.') && inet_aton(str, &addr) != 0) {
564 *mask = ntohl(addr.s_addr); /* We want host byte order */
567 if (sscanf(str, "%d", &bits) != 1 || bits < 0 || bits > 32)
568 exit_error(PARAMETER_PROBLEM,
569 "invalid mask `%s' specified", str);
571 DP("bits: %d", bits);
573 *mask = bits != 0 ? 0xFFFFFFFF << (32 - bits) : 0L;
576 /* Combines parse_ip and parse_mask */
578 parse_ipandmask(const char *str, ip_set_ip_t * ip, ip_set_ip_t * mask)
583 strncpy(buf, str, sizeof(buf) - 1);
586 if ((p = strrchr(buf, '/')) != NULL) {
588 parse_mask(p + 1, mask);
590 parse_mask(NULL, mask);
592 /* if a null mask is given, the name is ignored, like in "any/0" */
598 DP("%s ip: %08X (%s) mask: %08X",
599 str, *ip, ip_tostring_numeric(*ip), *mask);
601 /* Apply the netmask */
604 DP("%s ip: %08X (%s) mask: %08X",
605 str, *ip, ip_tostring_numeric(*ip), *mask);
608 /* Return a string representation of a port
609 * Please notice that a pointer to static char* area is returned
610 * and we assume TCP protocol.
612 char *port_tostring(ip_set_ip_t port, unsigned options)
614 struct servent *service;
615 static char name[] = "65535";
617 if (!(options & OPT_NUMERIC)) {
618 if ((service = getservbyport(htons(port), "tcp")))
619 return service->s_name;
621 sprintf(name, "%u", port);
626 string_to_number(const char *str, unsigned int min, unsigned int max,
632 /* Handle hex, octal, etc. */
634 number = strtol(str, &end, 0);
635 if (*end == '\0' && end != str) {
636 /* we parsed a number, let's see if we want this */
637 if (errno != ERANGE && min <= number && number <= max) {
646 string_to_port(const char *str, ip_set_ip_t *port)
648 struct servent *service;
650 if ((service = getservbyname(str, "tcp")) != NULL) {
651 *port = ntohs((unsigned short) service->s_port);
658 /* Fills the 'ip' with the parsed port in host byte order */
659 void parse_port(const char *str, ip_set_ip_t *port)
661 if ((string_to_number(str, 0, 65535, port) != 0)
662 && (string_to_port(str, port) != 0))
663 exit_error(PARAMETER_PROBLEM,
664 "Invalid TCP port `%s' specified", str);
670 static struct settype *settype_find(const char *typename)
672 struct settype *runner = all_settypes;
676 while (runner != NULL) {
677 if (strncmp(runner->typename, typename,
678 IP_SET_MAXNAMELEN) == 0)
681 runner = runner->next;
684 return NULL; /* not found */
687 static struct settype *settype_load(const char *typename)
689 char path[sizeof(IPSET_LIB_DIR) + sizeof(IPSET_LIB_NAME) +
691 struct settype *settype;
693 /* do some search in list */
694 settype = settype_find(typename);
696 return settype; /* found */
698 /* Else we have to load it */
699 sprintf(path, IPSET_LIB_DIR IPSET_LIB_NAME, typename);
701 if (dlopen(path, RTLD_NOW)) {
704 settype = settype_find(typename);
710 /* Can't load the settype */
711 exit_error(PARAMETER_PROBLEM,
712 "Couldn't load settype `%s':%s\n",
713 typename, dlerror());
715 return NULL; /* Never executed, but keep compilers happy */
718 static char *check_set_name(char *setname)
720 if (strlen(setname) > IP_SET_MAXNAMELEN - 1)
721 exit_error(PARAMETER_PROBLEM,
722 "Setname '%s' too long, max %d characters.",
723 setname, IP_SET_MAXNAMELEN - 1);
728 static struct settype *check_set_typename(const char *typename)
730 if (strlen(typename) > IP_SET_MAXNAMELEN - 1)
731 exit_error(PARAMETER_PROBLEM,
732 "Typename '%s' too long, max %d characters.",
733 typename, IP_SET_MAXNAMELEN - 1);
735 return settype_load(typename);
738 #define MAX(a,b) ((a) > (b) ? (a) : (b))
740 /* Register a new set type */
741 void settype_register(struct settype *settype)
746 DP("%s", settype->typename);
748 /* Check if this typename already exists */
749 chk = settype_find(settype->typename);
752 exit_error(OTHER_PROBLEM,
753 "Set type '%s' already registered!\n",
757 if (settype->protocol_version != IP_SET_PROTOCOL_VERSION)
758 exit_error(OTHER_PROBLEM,
759 "Set type %s is of wrong protocol version %u!"
760 " I'm of version %u.\n", settype->typename,
761 settype->protocol_version,
762 IP_SET_PROTOCOL_VERSION);
764 /* Initialize internal data */
765 settype->header = ipset_malloc(settype->header_size);
766 size = MAX(settype->create_size, settype->adt_size);
767 settype->data = ipset_malloc(size);
770 settype->next = all_settypes;
771 all_settypes = settype;
773 DP("%s registered", settype->typename);
776 /* Find set functions */
777 static struct set *set_find_byid(ip_set_id_t id)
779 struct set *set = NULL;
782 for (i = 0; i < max_sets; i++)
783 if (set_list[i] && set_list[i]->id == id) {
789 exit_error(PARAMETER_PROBLEM,
790 "Set identified by id %u is not found", id);
794 static struct set *set_find_byname(const char *name)
796 struct set *set = NULL;
799 for (i = 0; i < max_sets; i++)
801 && strncmp(set_list[i]->name, name,
802 IP_SET_MAXNAMELEN) == 0) {
807 exit_error(PARAMETER_PROBLEM,
808 "Set %s is not found", name);
812 static ip_set_id_t set_find_free_index(const char *name)
814 ip_set_id_t i, index = IP_SET_INVALID_ID;
816 for (i = 0; i < max_sets; i++) {
817 if (index == IP_SET_INVALID_ID
818 && set_list[i] == NULL)
820 if (set_list[i] != NULL
821 && strncmp(set_list[i]->name, name,
822 IP_SET_MAXNAMELEN) == 0)
823 exit_error(PARAMETER_PROBLEM,
824 "Set %s is already defined, cannot be restored",
828 if (index == IP_SET_INVALID_ID)
829 exit_error(PARAMETER_PROBLEM,
830 "Set %s cannot be restored, "
831 "max number of set %u reached",
838 * Send create set order to kernel
840 static void set_create(const char *name, struct settype *settype)
842 struct ip_set_req_create req_create;
846 DP("%s %s", name, settype->typename);
848 req_create.op = IP_SET_OP_CREATE;
849 req_create.version = IP_SET_PROTOCOL_VERSION;
850 strcpy(req_create.name, name);
851 strcpy(req_create.typename, settype->typename);
854 settype->create_final(settype->data, settype->flags);
856 /* Alloc memory for the data to send */
857 size = sizeof(struct ip_set_req_create) + settype->create_size;
858 data = ipset_malloc(size);
860 /* Add up ip_set_req_create and the settype data */
861 memcpy(data, &req_create, sizeof(struct ip_set_req_create));
862 memcpy(data + sizeof(struct ip_set_req_create),
863 settype->data, settype->create_size);
865 kernel_sendto(CMD_CREATE, data, size);
869 static void set_restore_create(const char *name, struct settype *settype)
873 DP("%s %s %u %u %u %u", name, settype->typename,
874 restore_offset, sizeof(struct ip_set_restore),
875 settype->create_size, restore_size);
877 /* Sanity checking */
879 + sizeof(struct ip_set_restore)
880 + settype->create_size > restore_size)
881 exit_error(PARAMETER_PROBLEM,
882 "Giving up, restore file is screwed up!");
885 settype->create_final(settype->data, settype->flags);
887 /* Fill out restore_data */
888 restore_set = (struct ip_set_restore *)
889 (restore_data + restore_offset);
890 strcpy(restore_set->name, name);
891 strcpy(restore_set->typename, settype->typename);
892 restore_set->index = set_find_free_index(name);
893 restore_set->header_size = settype->create_size;
894 restore_set->members_size = 0;
896 DP("name %s, restore index %u", restore_set->name, restore_set->index);
897 /* Add settype data */
899 memcpy(restore_data + restore_offset + sizeof(struct ip_set_restore),
900 settype->data, settype->create_size);
902 restore_offset += sizeof(struct ip_set_restore)
903 + settype->create_size;
905 /* Add set to set_list */
906 set = ipset_malloc(sizeof(struct set));
907 strcpy(set->name, name);
908 set->settype = settype;
909 set->index = restore_set->index;
910 set_list[restore_set->index] = set;
914 * Send destroy/flush order to kernel for one or all sets
916 static void set_destroy(const char *name, unsigned op, unsigned cmd)
918 struct ip_set_req_std req;
920 DP("%s %s", cmd == CMD_DESTROY ? "destroy" : "flush", name);
923 req.version = IP_SET_PROTOCOL_VERSION;
924 strcpy(req.name, name);
926 kernel_sendto(cmd, &req, sizeof(struct ip_set_req_std));
930 * Send rename/swap order to kernel
932 static void set_rename(const char *name, const char *newname,
933 unsigned op, unsigned cmd)
935 struct ip_set_req_create req;
937 DP("%s %s %s", cmd == CMD_RENAME ? "rename" : "swap",
941 req.version = IP_SET_PROTOCOL_VERSION;
942 strcpy(req.name, name);
943 strcpy(req.typename, newname);
945 kernel_sendto(cmd, &req,
946 sizeof(struct ip_set_req_create));
950 * Send MAX_SETS, LIST_SIZE and/or SAVE_SIZE orders to kernel
952 static size_t load_set_list(const char name[IP_SET_MAXNAMELEN],
954 unsigned op, unsigned cmd)
957 struct ip_set_req_max_sets req_max_sets;
958 struct ip_set_name_list *name_list;
961 size_t size, req_size;
962 int repeated = 0, res = 0;
964 DP("%s %s", cmd == CMD_MAX_SETS ? "MAX_SETS"
965 : cmd == CMD_LIST_SIZE ? "LIST_SIZE"
971 for (i = 0; i < max_sets; i++)
978 req_max_sets.op = IP_SET_OP_MAX_SETS;
979 req_max_sets.version = IP_SET_PROTOCOL_VERSION;
980 strcpy(req_max_sets.set.name, name);
981 size = sizeof(req_max_sets);
982 kernel_getfrom(CMD_MAX_SETS, &req_max_sets, &size);
984 DP("got MAX_SETS: sets %d, max_sets %d",
985 req_max_sets.sets, req_max_sets.max_sets);
987 max_sets = req_max_sets.max_sets;
988 set_list = ipset_malloc(max_sets * sizeof(struct set *));
989 memset(set_list, 0, max_sets * sizeof(struct set *));
990 *index = req_max_sets.set.index;
992 if (req_max_sets.sets == 0)
993 /* No sets in kernel */
997 size = req_size = sizeof(struct ip_set_req_setnames)
998 + req_max_sets.sets * sizeof(struct ip_set_name_list);
999 data = ipset_malloc(size);
1000 ((struct ip_set_req_setnames *) data)->op = op;
1001 ((struct ip_set_req_setnames *) data)->index = *index;
1003 res = kernel_getfrom_handleerrno(cmd, data, &size);
1005 if (res != 0 || size != req_size) {
1007 if (repeated++ < LIST_TRIES)
1009 exit_error(OTHER_PROBLEM,
1010 "Tried to get sets from kernel %d times"
1011 " and failed. Please try again when the load on"
1012 " the sets has gone down.", LIST_TRIES);
1015 /* Load in setnames */
1016 size = sizeof(struct ip_set_req_setnames);
1017 while (size + sizeof(struct ip_set_name_list) <= req_size) {
1018 name_list = (struct ip_set_name_list *)
1020 set = ipset_malloc(sizeof(struct set));
1021 strcpy(set->name, name_list->name);
1022 set->index = name_list->index;
1023 set->id = name_list->id;
1024 set->settype = settype_load(name_list->typename);
1025 set_list[name_list->index] = set;
1026 DP("loaded %s, type %s, index %u",
1027 set->name, set->settype->typename, set->index);
1028 size += sizeof(struct ip_set_name_list);
1030 /* Size to get set members, bindings */
1031 size = ((struct ip_set_req_setnames *)data)->size;
1040 static size_t save_bindings(void *data, size_t offset, size_t len)
1042 struct ip_set_hash_save *hash =
1043 (struct ip_set_hash_save *) (data + offset);
1046 DP("offset %u, len %u", offset, len);
1047 if (offset + sizeof(struct ip_set_hash_save) > len)
1048 exit_error(OTHER_PROBLEM,
1049 "Save operation failed, try again later.");
1051 set = set_find_byid(hash->id);
1052 if (!(set && set_list[hash->binding]))
1053 exit_error(OTHER_PROBLEM,
1054 "Save binding failed, try again later.");
1055 printf("-B %s %s -b %s\n",
1057 set->settype->bindip_tostring(set, hash->ip, OPT_NUMERIC),
1058 set_list[hash->binding]->name);
1060 return sizeof(struct ip_set_hash_save);
1063 static size_t save_set(void *data, int *bindings,
1064 size_t offset, size_t len)
1066 struct ip_set_save *set_save =
1067 (struct ip_set_save *) (data + offset);
1069 struct settype *settype;
1072 DP("offset %u, len %u", offset, len);
1073 if (offset + sizeof(struct ip_set_save) > len
1074 || offset + sizeof(struct ip_set_save)
1075 + set_save->header_size + set_save->members_size > len)
1076 exit_error(OTHER_PROBLEM,
1077 "Save operation failed, try again later.");
1079 if (set_save->index == IP_SET_INVALID_ID) {
1082 return sizeof(struct ip_set_save);
1084 set = set_list[set_save->index];
1086 exit_error(OTHER_PROBLEM,
1087 "Save set failed, try again later.");
1088 settype = set->settype;
1090 /* Init set header */
1091 used = sizeof(struct ip_set_save);
1092 settype->initheader(set, data + offset + used);
1094 /* Print create set */
1095 settype->saveheader(set, OPT_NUMERIC);
1098 used += set_save->header_size;
1099 settype->saveips(set, data + offset + used,
1100 set_save->members_size, OPT_NUMERIC);
1102 return (used + set_save->members_size);
1105 static size_t save_default_bindings(void *data, int *bindings)
1107 struct ip_set_save *set_save = (struct ip_set_save *) data;
1110 if (set_save->index == IP_SET_INVALID_ID) {
1113 return sizeof(struct ip_set_save);
1116 set = set_list[set_save->index];
1117 DP("%s, binding %u", set->name, set_save->binding);
1118 if (set_save->binding != IP_SET_INVALID_ID) {
1119 if (!set_list[set_save->binding])
1120 exit_error(OTHER_PROBLEM,
1121 "Save set failed, try again later.");
1123 printf("-B %s %s -b %s\n",
1124 set->name, IPSET_TOKEN_DEFAULT,
1125 set_list[set_save->binding]->name);
1127 return (sizeof(struct ip_set_save)
1128 + set_save->header_size
1129 + set_save->members_size);
1132 static int try_save_sets(const char name[IP_SET_MAXNAMELEN])
1135 size_t size, req_size = 0;
1137 int res = 0, bindings = 0;
1138 time_t now = time(NULL);
1140 /* Load set_list from kernel */
1141 size = load_set_list(name, &index,
1142 IP_SET_OP_SAVE_SIZE, CMD_SAVE);
1145 /* Get sets, bindings and print them */
1146 /* Take into account marker */
1147 req_size = (size += sizeof(struct ip_set_save));
1148 data = ipset_malloc(size);
1149 ((struct ip_set_req_list *) data)->op = IP_SET_OP_SAVE;
1150 ((struct ip_set_req_list *) data)->index = index;
1151 res = kernel_getfrom_handleerrno(CMD_SAVE, data, &size);
1153 if (res != 0 || size != req_size) {
1159 printf("# Generated by ipset %s on %s", IPSET_VERSION, ctime(&now));
1161 while (size < req_size) {
1162 DP("size: %u, req_size: %u", size, req_size);
1164 size += save_bindings(data, size, req_size);
1166 size += save_set(data, &bindings, size, req_size);
1168 /* Re-read data to save default bindings */
1171 while (size < req_size && bindings == 0)
1172 size += save_default_bindings(data + size, &bindings);
1176 printf("# Completed on %s", ctime(&now));
1182 * Performs a save to stdout
1184 static void set_save(const char name[IP_SET_MAXNAMELEN])
1189 for (i = 0; i < LIST_TRIES; i++)
1190 if (try_save_sets(name) == 0)
1193 if (errno == EAGAIN)
1194 exit_error(OTHER_PROBLEM,
1195 "Tried to save sets from kernel %d times"
1196 " and failed. Please try again when the load on"
1197 " the sets has gone down.", LIST_TRIES);
1199 kernel_error(CMD_SAVE, errno);
1206 /* global new argv and argc */
1207 static char *newargv[255];
1208 static int newargc = 0;
1210 /* Build faked argv from parsed line */
1211 static void build_argv(int line, char *buffer) {
1216 for (i = 1; i < newargc; i++)
1220 ptr = strtok(buffer, " \t\n");
1221 newargv[newargc++] = ipset_strdup(ptr);
1222 while ((ptr = strtok(NULL, " \t\n")) != NULL) {
1223 if ((newargc + 1) < sizeof(newargv)/sizeof(char *))
1224 newargv[newargc++] = ipset_strdup(ptr);
1226 exit_error(PARAMETER_PROBLEM,
1227 "Line %d is too long to restore\n", line);
1231 static FILE *create_tempfile(void)
1234 char *tmpdir = NULL;
1239 if (!(tmpdir = getenv("TMPDIR")) && !(tmpdir = getenv("TMP")))
1241 filename = ipset_malloc(strlen(tmpdir) + strlen(TEMPFILE_PATTERN) + 1);
1242 strcpy(filename, tmpdir);
1243 strcat(filename, TEMPFILE_PATTERN);
1245 (void) umask(077); /* Create with restrictive permissions */
1246 fd = mkstemp(filename);
1248 exit_error(OTHER_PROBLEM, "Could not create temporary file.");
1249 if (!(file = fdopen(fd, "r+")))
1250 exit_error(OTHER_PROBLEM, "Could not open temporary file.");
1251 if (unlink(filename) == -1)
1252 exit_error(OTHER_PROBLEM, "Could not unlink temporary file.");
1255 while (fgets(buffer, sizeof(buffer), stdin)) {
1256 fputs(buffer, file);
1258 fseek(file, 0L, SEEK_SET);
1264 * Performs a restore from a file
1266 static void set_restore(char *argv0)
1269 char *ptr, *name = NULL;
1271 int line = 0, first_pass, i, bindings = 0;
1272 struct settype *settype = NULL;
1273 struct ip_set_req_setnames *header;
1278 /* Create and store stdin in temporary file */
1279 in = create_tempfile();
1281 /* Load existing sets from kernel */
1282 load_set_list(IPSET_TOKEN_ALL, &index,
1283 IP_SET_OP_LIST_SIZE, CMD_RESTORE);
1285 restore_size = sizeof(struct ip_set_req_setnames)/* header */
1286 + sizeof(struct ip_set_restore); /* marker */
1287 DP("restore_size: %u", restore_size);
1288 /* First pass: calculate required amount of data */
1289 while (fgets(buffer, sizeof(buffer), in)) {
1292 if (buffer[0] == '\n')
1294 else if (buffer[0] == '#')
1296 else if (strcmp(buffer, "COMMIT\n") == 0) {
1297 /* Enable restore mode */
1303 ptr = strtok(buffer, " \t\n");
1310 || ptr[2] != '\0') {
1311 exit_error(PARAMETER_PROBLEM,
1312 "Line %u does not start as a valid restore command\n",
1317 ptr = strtok(NULL, " \t\n");
1318 DP("setname: %s", ptr);
1320 exit_error(PARAMETER_PROBLEM,
1321 "Missing set name in line %u\n",
1326 name = check_set_name(ptr);
1328 ptr = strtok(NULL, " \t\n");
1330 exit_error(PARAMETER_PROBLEM,
1331 "Missing settype in line %u\n",
1334 exit_error(PARAMETER_PROBLEM,
1335 "Invalid line %u: create must precede bindings\n",
1337 settype = check_set_typename(ptr);
1338 restore_size += sizeof(struct ip_set_restore)
1339 + settype->create_size;
1340 DP("restore_size (N): %u", restore_size);
1345 || strncmp(name, ptr, sizeof(name)) != 0)
1346 exit_error(PARAMETER_PROBLEM,
1347 "Add IP to set %s in line %u without "
1348 "preceding corresponding create set line\n",
1351 exit_error(PARAMETER_PROBLEM,
1352 "Invalid line %u: adding entries must precede bindings\n",
1354 restore_size += settype->adt_size;
1355 DP("restore_size (A): %u", restore_size);
1360 restore_size += sizeof(struct ip_set_hash_save);
1361 DP("restore_size (B): %u", restore_size);
1365 exit_error(PARAMETER_PROBLEM,
1366 "Unrecognized restore command in line %u\n",
1369 } /* end of switch */
1371 /* Sanity checking */
1373 exit_error(PARAMETER_PROBLEM,
1374 "Missing COMMIT line\n");
1375 DP("restore_size: %u", restore_size);
1376 restore_data = ipset_malloc(restore_size);
1377 header = (struct ip_set_req_setnames *) restore_data;
1378 header->op = IP_SET_OP_RESTORE;
1379 header->size = restore_size;
1380 restore_offset = sizeof(struct ip_set_req_setnames);
1382 /* Rewind to scan the file again */
1383 fseek(in, 0L, SEEK_SET);
1387 /* Initialize newargv/newargc */
1388 newargv[newargc++] = ipset_strdup(argv0);
1390 /* Second pass: build up restore request */
1391 while (fgets(buffer, sizeof(buffer), in)) {
1394 if (buffer[0] == '\n')
1396 else if (buffer[0] == '#')
1398 else if (strcmp(buffer, "COMMIT\n") == 0)
1400 DP("restoring: %s", buffer);
1401 /* Build faked argv, argc */
1402 build_argv(line, buffer);
1403 for (i = 0; i < newargc; i++)
1404 DP("argv[%u]: %s", i, newargv[i]);
1407 parse_commandline(newargc, newargv);
1409 exit_error(PARAMETER_PROBLEM,
1410 "Broken restore file\n");
1414 (restore_offset + sizeof(struct ip_set_restore))) {
1416 struct ip_set_restore *marker =
1417 (struct ip_set_restore *) (restore_data + restore_offset);
1419 DP("restore marker");
1420 marker->index = IP_SET_INVALID_ID;
1421 marker->header_size = marker->members_size = 0;
1422 restore_offset += sizeof(struct ip_set_restore);
1424 if (restore_size != restore_offset)
1425 exit_error(PARAMETER_PROBLEM,
1426 "Giving up, restore file is screwed up!");
1427 res = kernel_getfrom_handleerrno(CMD_RESTORE, restore_data, &restore_size);
1430 if (restore_size != sizeof(struct ip_set_req_setnames))
1431 exit_error(PARAMETER_PROBLEM,
1432 "Communication with kernel failed (%u %u)!",
1433 restore_size, sizeof(struct ip_set_req_setnames));
1435 header = (struct ip_set_req_setnames *) restore_data;
1436 if (header->size != 0)
1437 exit_error(PARAMETER_PROBLEM,
1438 "Committing restoring failed at line %u!",
1444 * Send ADT_GET order to kernel for a set
1446 static struct set *set_adt_get(const char *name)
1448 struct ip_set_req_adt_get req_adt_get;
1454 req_adt_get.op = IP_SET_OP_ADT_GET;
1455 req_adt_get.version = IP_SET_PROTOCOL_VERSION;
1456 strcpy(req_adt_get.set.name, name);
1457 size = sizeof(struct ip_set_req_adt_get);
1459 kernel_getfrom(CMD_ADT_GET, &req_adt_get, &size);
1461 set = ipset_malloc(sizeof(struct set));
1462 strcpy(set->name, name);
1463 set->index = req_adt_get.set.index;
1464 set->settype = settype_load(req_adt_get.typename);
1470 * Send add/del/test order to kernel for a set
1472 static int set_adtip(struct set *set, const char *adt,
1473 unsigned op, unsigned cmd)
1475 struct ip_set_req_adt *req_adt;
1480 DP("%s -> %s", set->name, adt);
1482 /* Alloc memory for the data to send */
1483 size = sizeof(struct ip_set_req_adt) + set->settype->adt_size ;
1484 DP("alloc size %i", size);
1485 data = ipset_malloc(size);
1487 /* Fill out the request */
1488 req_adt = (struct ip_set_req_adt *) data;
1490 req_adt->index = set->index;
1491 memcpy(data + sizeof(struct ip_set_req_adt),
1492 set->settype->data, set->settype->adt_size);
1494 if (kernel_sendto_handleerrno(cmd, op, data, size) == -1)
1496 case IP_SET_OP_ADD_IP:
1497 exit_error(OTHER_PROBLEM, "%s is already in set %s.",
1500 case IP_SET_OP_DEL_IP:
1501 exit_error(OTHER_PROBLEM, "%s is not in set %s.",
1504 case IP_SET_OP_TEST_IP:
1505 ipset_printf("%s is in set %s.", adt, set->name);
1513 case IP_SET_OP_TEST_IP:
1514 ipset_printf("%s is NOT in set %s.", adt, set->name);
1525 static void set_restore_add(struct set *set, const char *adt)
1527 DP("%s %s", set->name, adt);
1528 /* Sanity checking */
1529 if (restore_offset + set->settype->adt_size > restore_size)
1530 exit_error(PARAMETER_PROBLEM,
1531 "Giving up, restore file is screwed up!");
1533 memcpy(restore_data + restore_offset,
1534 set->settype->data, set->settype->adt_size);
1535 restore_set->members_size += set->settype->adt_size;
1536 restore_offset += set->settype->adt_size;
1540 * Send bind/unbind/test binding order to kernel for a set
1542 static int set_bind(struct set *set, const char *adt,
1543 const char *binding,
1544 unsigned op, unsigned cmd)
1546 struct ip_set_req_bind *req_bind;
1551 /* set may be null: '-U :all: :all:|:default:' */
1552 DP("(%s, %s) -> %s", set ? set->name : IPSET_TOKEN_ALL, adt, binding);
1554 /* Alloc memory for the data to send */
1555 size = sizeof(struct ip_set_req_bind);
1556 if (op != IP_SET_OP_UNBIND_SET && adt[0] == ':')
1557 /* Set default binding */
1558 size += IP_SET_MAXNAMELEN;
1559 else if (!(op == IP_SET_OP_UNBIND_SET && set == NULL))
1560 size += set->settype->adt_size;
1561 DP("alloc size %i", size);
1562 data = ipset_malloc(size);
1564 /* Fill out the request */
1565 req_bind = (struct ip_set_req_bind *) data;
1567 req_bind->index = set ? set->index : IP_SET_INVALID_ID;
1568 if (adt[0] == ':') {
1569 /* ':default:' and ':all:' */
1570 strncpy(req_bind->binding, adt, IP_SET_MAXNAMELEN);
1571 if (op != IP_SET_OP_UNBIND_SET && adt[0] == ':')
1572 strncpy(data + sizeof(struct ip_set_req_bind),
1573 binding, IP_SET_MAXNAMELEN);
1575 strncpy(req_bind->binding, binding, IP_SET_MAXNAMELEN);
1576 memcpy(data + sizeof(struct ip_set_req_bind),
1577 set->settype->data, set->settype->adt_size);
1580 if (op == IP_SET_OP_TEST_BIND_SET) {
1581 if (kernel_sendto_handleerrno(cmd, op, data, size) == -1) {
1582 ipset_printf("%s in set %s is bound to %s.",
1583 adt, set->name, binding);
1586 ipset_printf("%s in set %s is NOT bound to %s.",
1587 adt, set->name, binding);
1591 kernel_sendto(cmd, data, size);
1597 static void set_restore_bind(struct set *set,
1599 const char *binding)
1601 struct ip_set_hash_save *hash_restore;
1605 struct ip_set_restore *marker =
1606 (struct ip_set_restore *) (restore_data + restore_offset);
1608 DP("restore marker");
1609 if (restore_offset + sizeof(struct ip_set_restore)
1611 exit_error(PARAMETER_PROBLEM,
1612 "Giving up, restore file is screwed up!");
1613 marker->index = IP_SET_INVALID_ID;
1614 marker->header_size = marker->members_size = 0;
1615 restore_offset += sizeof(struct ip_set_restore);
1618 /* Sanity checking */
1619 if (restore_offset + sizeof(struct ip_set_hash_save) > restore_size)
1620 exit_error(PARAMETER_PROBLEM,
1621 "Giving up, restore file is screwed up!");
1623 hash_restore = (struct ip_set_hash_save *) (restore_data + restore_offset);
1624 DP("%s -> %s", adt, binding);
1625 if (strcmp(adt, IPSET_TOKEN_DEFAULT) == 0)
1626 hash_restore->ip = 0;
1628 set->settype->bindip_parse(adt, &hash_restore->ip);
1629 hash_restore->id = set->index;
1630 hash_restore->binding = (set_find_byname(binding))->index;
1631 DP("id %u, ip %u, binding %u",
1632 hash_restore->id, hash_restore->ip, hash_restore->binding);
1633 restore_offset += sizeof(struct ip_set_hash_save);
1640 static void print_bindings(struct set *set,
1641 void *data, size_t size, unsigned options,
1642 char * (*printip)(struct set *set,
1643 ip_set_ip_t ip, unsigned options))
1646 struct ip_set_hash_list *hash;
1648 while (offset < size) {
1649 hash = (struct ip_set_hash_list *) (data + offset);
1650 printf("%s -> %s\n",
1651 printip(set, hash->ip, options),
1652 set_list[hash->binding]->name);
1653 offset += sizeof(struct ip_set_hash_list);
1657 /* Help function to set_list() */
1658 static size_t print_set(void *data, unsigned options)
1660 struct ip_set_list *setlist = (struct ip_set_list *) data;
1661 struct set *set = set_list[setlist->index];
1662 struct settype *settype = set->settype;
1665 /* Pretty print the set */
1666 printf("Name: %s\n", set->name);
1667 printf("Type: %s\n", settype->typename);
1668 printf("References: %d\n", setlist->ref);
1669 printf("Default binding: %s\n",
1670 setlist->binding == IP_SET_INVALID_ID ? ""
1671 : set_list[setlist->binding]->name);
1674 offset = sizeof(struct ip_set_list);
1675 settype->initheader(set, data + offset);
1677 /* Pretty print the type header */
1679 settype->printheader(set, options);
1681 /* Pretty print all IPs */
1682 printf("Members:\n");
1683 offset += setlist->header_size;
1684 if (options & OPT_SORTED)
1685 settype->printips_sorted(set, data + offset,
1686 setlist->members_size, options);
1688 settype->printips(set, data + offset,
1689 setlist->members_size, options);
1691 /* Print bindings */
1692 printf("Bindings:\n");
1693 offset += setlist->members_size;
1695 data + offset, setlist->bindings_size, options,
1696 settype->bindip_tostring);
1698 printf("\n"); /* One newline between sets */
1700 return (offset + setlist->bindings_size);
1703 static int try_list_sets(const char name[IP_SET_MAXNAMELEN],
1708 size_t size, req_size;
1712 /* Load set_list from kernel */
1713 size = req_size = load_set_list(name, &index,
1714 IP_SET_OP_LIST_SIZE, CMD_LIST);
1717 /* Get sets and print them */
1718 data = ipset_malloc(size);
1719 ((struct ip_set_req_list *) data)->op = IP_SET_OP_LIST;
1720 ((struct ip_set_req_list *) data)->index = index;
1721 res = kernel_getfrom_handleerrno(CMD_LIST, data, &size);
1722 DP("get_lists getsockopt() res=%d errno=%d", res, errno);
1724 if (res != 0 || size != req_size) {
1730 while (size != req_size)
1731 size += print_set(data + size, options);
1737 /* Print a set or all sets
1738 * All sets: name = NULL
1740 static void list_sets(const char name[IP_SET_MAXNAMELEN], unsigned options)
1745 for (i = 0; i < LIST_TRIES; i++)
1746 if (try_list_sets(name, options) == 0)
1749 if (errno == EAGAIN)
1750 exit_error(OTHER_PROBLEM,
1751 "Tried to list sets from kernel %d times"
1752 " and failed. Please try again when the load on"
1753 " the sets has gone down.", LIST_TRIES);
1755 kernel_error(CMD_LIST, errno);
1759 * If settype is non null help for that type is printed as well
1761 static void set_help(const struct settype *settype)
1765 " --debug -z Enable debugging\n\n";
1767 char debughelp[] = "\n";
1771 "Usage: %s -N new-set settype [options]\n"
1772 " %s -[XFLSH] [set] [options]\n"
1773 " %s -[EW] from-set to-set\n"
1774 " %s -[ADTU] set IP\n"
1775 " %s -B set IP option\n"
1777 " %s -h (print this help information)\n\n",
1778 program_name, program_version,
1779 program_name, program_name, program_name,
1780 program_name, program_name, program_name,
1783 printf("Commands:\n"
1784 "Either long or short options are allowed.\n"
1785 " --create -N setname settype <options>\n"
1786 " Create a new set\n"
1787 " --destroy -X [setname]\n"
1788 " Destroy a set or all sets\n"
1789 " --flush -F [setname]\n"
1790 " Flush a set or all sets\n"
1791 " --rename -E from-set to-set\n"
1792 " Rename from-set to to-set\n"
1793 " --swap -W from-set to-set\n"
1794 " Swap the content of two existing sets\n"
1795 " --list -L [setname] [options]\n"
1796 " List the IPs in a set or all sets\n"
1797 " --save -S [setname]\n"
1798 " Save the set or all sets to stdout\n"
1799 " --restore -R [option]\n"
1800 " Restores a saved state\n"
1801 " --add -A setname IP\n"
1802 " Add an IP to a set\n"
1803 " --del -D setname IP\n"
1804 " Deletes an IP from a set\n"
1805 " --test -T setname IP \n"
1806 " Tests if an IP exists in a set.\n"
1807 " --bind -B setname IP|:default: -b bind-setname\n"
1808 " Bind the IP in setname to bind-setname.\n"
1809 " --unbind -U setname IP|:all:|:default:\n"
1810 " Delete binding belonging to IP,\n"
1811 " all bindings or default binding of setname.\n"
1812 " --unbind -U :all: :all:|:default:\n"
1813 " Delete all bindings or all default bindings.\n"
1814 " --help -H [settype]\n"
1815 " Prints this help, and settype specific help\n"
1817 " Prints version information\n\n"
1819 " --sorted -s Numeric sort of the IPs in -L\n"
1820 " --numeric -n Numeric output of addresses in a -L\n"
1821 " --quiet -q Suppress any output to stdout and stderr.\n"
1822 " --binding -b Specifies the binding for -B\n");
1825 if (settype != NULL) {
1826 printf("Type '%s' specific:\n", settype->typename);
1831 static int find_cmd(const char option)
1835 for (i = 1; i <= NUMBER_OF_CMD; i++)
1836 if (cmdflags[i] == option)
1842 static int parse_adt_cmdline(unsigned command,
1846 struct settype **settype)
1850 /* -U :all: :all:|:default: */
1851 if (command == CMD_UNBIND) {
1852 if (strcmp(name, IPSET_TOKEN_ALL) == 0) {
1853 if (strcmp(adt, IPSET_TOKEN_DEFAULT) == 0
1854 || strcmp(adt, IPSET_TOKEN_ALL) == 0) {
1859 exit_error(PARAMETER_PROBLEM,
1860 "-U %s requires %s or %s as binding name",
1862 IPSET_TOKEN_DEFAULT,
1866 *set = restore ? set_find_byname(name)
1867 : set_adt_get(name);
1869 /* Reset space for adt data */
1870 *settype = (*set)->settype;
1871 memset((*settype)->data, 0, (*settype)->adt_size);
1873 if ((command == CMD_TEST
1874 || command == CMD_BIND
1875 || command == CMD_UNBIND)
1876 && (strcmp(adt, IPSET_TOKEN_DEFAULT) == 0
1877 || strcmp(adt, IPSET_TOKEN_ALL) == 0))
1880 res = (*settype)->adt_parser(
1888 /* Main worker function */
1889 int parse_commandline(int argc, char *argv[])
1892 unsigned command = CMD_NONE;
1893 unsigned options = 0;
1896 char *name = NULL; /* All except -H, -R */
1897 char *newname = NULL; /* -E, -W */
1898 char *adt = NULL; /* -A, -D, -T, -B, -U */
1899 char *binding = NULL; /* -B */
1900 struct set *set = NULL; /* -A, -D, -T, -B, -U */
1901 struct settype *settype = NULL; /* -N, -H */
1902 char all_sets[] = IPSET_TOKEN_ALL;
1904 struct option *opts = opts_long;
1906 /* Suppress error messages: we may add new options if we
1907 demand-load a protocol. */
1909 /* Reset optind to 0 for restore */
1912 while ((c = getopt_long(argc, argv, opts_short, opts, NULL)) != -1) {
1914 DP("commandline parsed: opt %c (%s)", c, argv[optind]);
1921 case 'H':{ /* Help: -H [typename [options]] */
1922 check_protocolversion();
1923 set_command(&command, CMD_HELP);
1926 settype = check_set_typename(optarg);
1927 else if (optind < argc
1928 && argv[optind][0] != '-')
1929 settype = check_set_typename(argv[optind++]);
1934 case 'V':{ /* Version */
1935 printf("%s v%s Protocol version %u.\n",
1936 program_name, program_version,
1937 IP_SET_PROTOCOL_VERSION);
1938 check_protocolversion();
1942 case 'N':{ /* Create: -N name typename options */
1943 set_command(&command, CMD_CREATE);
1945 name = check_set_name(optarg);
1947 /* Protect reserved names (binding) */
1949 exit_error(PARAMETER_PROBLEM,
1950 "setname might not start with colon",
1951 cmd2char(CMD_CREATE));
1954 && argv[optind][0] != '-')
1955 settype = check_set_typename(argv[optind++]);
1957 exit_error(PARAMETER_PROBLEM,
1958 "-%c requires setname and settype",
1959 cmd2char(CMD_CREATE));
1961 DP("merge options");
1962 /* Merge the create options */
1963 opts = merge_options(opts,
1964 settype->create_opts,
1965 &settype->option_offset);
1967 /* Reset space for create data */
1968 memset(settype->data, 0, settype->create_size);
1970 /* Zero the flags */
1973 DP("call create_init");
1974 /* Call the settype create_init */
1975 settype->create_init(settype->data);
1980 case 'X': /* Destroy */
1981 case 'F': /* Flush */
1982 case 'L': /* List */
1983 case 'S':{ /* Save */
1984 set_command(&command, find_cmd(c));
1987 name = check_set_name(optarg);
1988 else if (optind < argc
1989 && argv[optind][0] != '-')
1990 name = check_set_name(argv[optind++]);
1997 case 'R':{ /* Restore */
1998 set_command(&command, find_cmd(c));
2003 case 'E': /* Rename */
2004 case 'W':{ /* Swap */
2005 set_command(&command, find_cmd(c));
2006 name = check_set_name(optarg);
2009 && argv[optind][0] != '-')
2010 newname = check_set_name(argv[optind++]);
2012 exit_error(PARAMETER_PROBLEM,
2013 "-%c requires a setname "
2014 "and the new name for that set",
2015 cmd2char(CMD_RENAME));
2020 case 'A': /* Add IP */
2021 case 'D': /* Del IP */
2022 case 'T': /* Test IP */
2023 case 'B': /* Bind IP */
2024 case 'U':{ /* Unbind IP */
2025 set_command(&command, find_cmd(c));
2027 name = check_set_name(optarg);
2031 && argv[optind][0] != '-')
2032 adt = argv[optind++];
2034 exit_error(PARAMETER_PROBLEM,
2035 "-%c requires setname and IP",
2038 res = parse_adt_cmdline(command, name, adt,
2042 exit_error(PARAMETER_PROBLEM,
2052 add_option(&options, OPT_NUMERIC);
2056 add_option(&options, OPT_SORTED);
2060 add_option(&options, OPT_QUIET);
2065 case 'z': /* debug */
2066 add_option(&options, OPT_DEBUG);
2072 add_option(&options, OPT_BINDING);
2073 binding = check_set_name(optarg);
2076 case 1: /* non option */
2077 printf("Bad argument `%s'\n", optarg);
2079 break; /*always good */
2086 res = settype->create_parse(
2087 c - settype->option_offset,
2094 res = 0; /* failed */
2095 } /* switch (command) */
2099 exit_error(PARAMETER_PROBLEM,
2108 } /* while( getopt_long() ) */
2112 exit_error(PARAMETER_PROBLEM,
2113 "unknown arguments found on commandline");
2114 if (command == CMD_NONE)
2115 exit_error(PARAMETER_PROBLEM, "no command specified");
2118 generic_opt_check(command, options);
2120 DP("cmd: %c", cmd2char(command));
2126 set_restore_create(name, settype);
2128 set_create(name, settype);
2132 set_destroy(name, IP_SET_OP_DESTROY, CMD_DESTROY);
2136 set_destroy(name, IP_SET_OP_FLUSH, CMD_FLUSH);
2140 set_rename(name, newname, IP_SET_OP_RENAME, CMD_RENAME);
2144 set_rename(name, newname, IP_SET_OP_SWAP, CMD_SWAP);
2148 list_sets(name, options);
2156 set_restore(argv[0]);
2161 set_restore_add(set, adt);
2163 set_adtip(set, adt, IP_SET_OP_ADD_IP, CMD_ADD);
2167 set_adtip(set, adt, IP_SET_OP_DEL_IP, CMD_DEL);
2172 res = set_bind(set, adt, binding,
2173 IP_SET_OP_TEST_BIND_SET, CMD_TEST);
2175 res = set_adtip(set, adt,
2176 IP_SET_OP_TEST_IP, CMD_TEST);
2181 set_restore_bind(set, adt, binding);
2183 set_bind(set, adt, binding,
2184 IP_SET_OP_BIND_SET, CMD_BIND);
2188 set_bind(set, adt, "", IP_SET_OP_UNBIND_SET, CMD_UNBIND);
2196 /* Will never happen */
2197 break; /* Keep the compiler happy */
2199 } /* switch( command ) */
2205 int main(int argc, char *argv[])
2207 return parse_commandline(argc, argv);