iptables: Sort table names in ip[6]tables-save
PATCH v3 1/1 iptables: Sort table names in ip[6]tables-save
Depending upon the load order of rules, the output from ip[6]tables-save will vary, as ip[6]_tables_names is sorted LIFO. As reported by Linus van Geuns, this makes comparing output from ip[6]tables-save across reboots difficult. Attached are two patches which attempt to fix this.
1) Sort by default - add 'u' option to unsort
2) Unsorted by default - add 's' option to sort
Please apply whichever is preferable.
This closes bugzilla #580.
Phil
---
v2: Add option to disable sorting - feedback from Maciej Żenczykowski
v3: Provide two patches
include/xtables.h +2 -0
@@ -479,6 +479,8 @@ extern void xtables_ip6parse_any(const char *, struct in6_addr **,extern void xtables_ip6parse_multiple (const char *,struct in6_addr **,struct in6_addr **,unsigned int *); +extern int stringcmp (const void *,const void *); +/** * Print the specified value to standard output, quoting dangerous * characters if required.
iptables/ip6tables-save.8 +4 -0
@@ -39,6 +39,10 @@ include the current values of all packet and byte counters in the output \fB\-t\fR, \fB\-\-table\fR \fItablename\fP restrict output to only one table. If not specified, output includes all available tables. +.TP +\fB\-u\fR, \fB\-\-unsorted\fR +by default, tables are output in alphabetical order. This option disables +sorting, and tables are output in LIFO order. .SH BUGS None known as of iptables-1.2.1 release .SH AUTHORS
iptables/ip6tables-save.c +19 -4
@@ -9,6 +9,7 @@#include <sys/errno.h> #include <stdio.h> #include <fcntl.h> +#include <stdbool.h> #include <stdlib.h> #include <string.h> #include <time.h>
@@ -23,12 +24,14 @@#endif static int show_counters =0 ; +static bool sort_tables = true;static const struct option options[] = { {.name ="counters" , .has_arg = false, .val ='c' }, {.name ="dump" , .has_arg = false, .val ='d' }, {.name ="table" , .has_arg = true, .val ='t' }, {.name ="modprobe" , .has_arg = true, .val ='M' }, + {.name ="unsorted" , .has_arg = false, .val ='u' }, {NULL }, };
@@ -36,8 +39,9 @@ static const struct option options[] = {/* Debugging prototype. */ static int for_each_table (int (*func)(const char *tablename)) { -int ret =1 ; +int i, count =0 , ret =1 ;FILE *procfile =NULL ; +char **tables =NULL ;char tablename[XT_TABLE_MAXNAMELEN +1 ]; procfile =fopen ("/proc/net/ip6_tables_names" ,"re" );
@@ -50,10 +54,18 @@ static int for_each_table(int (*func)(const char *tablename))"Badly formed tablename `%s'\n" , tablename); tablename[strlen (tablename) -1 ] ='\0' ; - ret &=func (tablename); + count++; + tables = (char **)realloc (tables,sizeof (char *)*count); + tables[count-1 ] =strdup (tablename); } -fclose (procfile); + +if (sort_tables == true) +qsort (tables, count,sizeof (char *), stringcmp); +for (i =0 ; i < count ; i++) { + ret &=func (tables[i]); + } +return ret; }
@@ -141,7 +153,7 @@ int ip6tables_save_main(int argc, char *argv[])init_extensions6 ();#endif -while ((c =getopt_long (argc, argv,"bcdt:" , options,NULL )) !=-1 ) { +while ((c =getopt_long (argc, argv,"bcdt:u" , options,NULL )) !=-1 ) {switch (c) {case 'c' : show_counters =1 ;
@@ -154,6 +166,9 @@ int ip6tables_save_main(int argc, char *argv[])case 'M' : xtables_modprobe_program = optarg;break ; +case 'u' : + sort_tables = false; +break ;case 'd' :do_output (tablename);exit (0 );
iptables/iptables-save.8 +4 -0
@@ -39,6 +39,10 @@ include the current values of all packet and byte counters in the output \fB\-t\fR, \fB\-\-table\fR \fItablename\fP restrict output to only one table. If not specified, output includes all available tables. +.TP +\fB\-u\fR, \fB\-\-unsorted\fR +by default, tables are output in alphabetical order. This option disables +sorting, and tables are output in LIFO order. .SH BUGS None known as of iptables-1.2.1 release .SH AUTHOR
iptables/iptables-save.c +19 -4
@@ -9,6 +9,7 @@#include <sys/errno.h> #include <stdio.h> #include <fcntl.h> +#include <stdbool.h> #include <stdlib.h> #include <string.h> #include <time.h>
@@ -22,20 +23,23 @@#endif static int show_counters =0 ; +static bool sort_tables = true;static const struct option options[] = { {.name ="counters" , .has_arg = false, .val ='c' }, {.name ="dump" , .has_arg = false, .val ='d' }, {.name ="table" , .has_arg = true, .val ='t' }, {.name ="modprobe" , .has_arg = true, .val ='M' }, + {.name ="unsorted" , .has_arg = false, .val ='u' }, {NULL }, };/* Debugging prototype. */ static int for_each_table (int (*func)(const char *tablename)) { -int ret =1 ; +int i, count =0 , ret =1 ;FILE *procfile =NULL ; +char **tables =NULL ;char tablename[XT_TABLE_MAXNAMELEN +1 ]; procfile =fopen ("/proc/net/ip_tables_names" ,"re" );
@@ -48,10 +52,18 @@ static int for_each_table(int (*func)(const char *tablename))"Badly formed tablename `%s'\n" , tablename); tablename[strlen (tablename) -1 ] ='\0' ; - ret &=func (tablename); + count++; + tables = (char **)realloc (tables,sizeof (char *)*count); + tables[count-1 ] =strdup (tablename); } -fclose (procfile); + +if (sort_tables == true) +qsort (tables, count,sizeof (char *), stringcmp); +for (i =0 ; i < count ; i++) { + ret &=func (tables[i]); + } +return ret; }
@@ -140,7 +152,7 @@ iptables_save_main(int argc, char *argv[])init_extensions4 ();#endif -while ((c =getopt_long (argc, argv,"bcdt:" , options,NULL )) !=-1 ) { +while ((c =getopt_long (argc, argv,"bcdt:u" , options,NULL )) !=-1 ) {switch (c) {case 'c' : show_counters =1 ;
@@ -153,6 +165,9 @@ iptables_save_main(int argc, char *argv[])case 'M' : xtables_modprobe_program = optarg;break ; +case 'u' : + sort_tables = false; +break ;case 'd' :do_output (tablename);exit (0 );
libxtables/xtables.c +7 -0
@@ -1961,3 +1961,10 @@ void get_kernel_version(void)sscanf (uts.release,"%d.%d.%d" , &x, &y, &z); kernel_version =LINUX_VERSION (x, y, z); } + +int stringcmp (const void *a,const void *b) +{ +const char **ia = (const char **)a; +const char **ib = (const char **)b; +return strcmp (*ia, *ib); +}
include/xtables.h +2 -0
@@ -479,6 +479,8 @@ extern void xtables_ip6parse_any(const char *, struct in6_addr **,extern void xtables_ip6parse_multiple (const char *,struct in6_addr **,struct in6_addr **,unsigned int *); +extern int stringcmp (const void *,const void *); +/** * Print the specified value to standard output, quoting dangerous * characters if required.
iptables/ip6tables-save.8 +4 -0
@@ -39,6 +39,10 @@ include the current values of all packet and byte counters in the output \fB\-t\fR, \fB\-\-table\fR \fItablename\fP restrict output to only one table. If not specified, output includes all available tables. +.TP +\fB\-s\fR, \fB\-\-sorted\fR +by default, tables are output in LIFO order. This option enables +sorting, and tables are output in alphabetical order. .SH BUGS None known as of iptables-1.2.1 release .SH AUTHORS
iptables/ip6tables-save.c +19 -4
@@ -9,6 +9,7 @@#include <sys/errno.h> #include <stdio.h> #include <fcntl.h> +#include <stdbool.h> #include <stdlib.h> #include <string.h> #include <time.h>
@@ -23,12 +24,14 @@#endif static int show_counters =0 ; +static bool sort_tables = false;static const struct option options[] = { {.name ="counters" , .has_arg = false, .val ='c' }, {.name ="dump" , .has_arg = false, .val ='d' }, {.name ="table" , .has_arg = true, .val ='t' }, {.name ="modprobe" , .has_arg = true, .val ='M' }, + {.name ="sorted" , .has_arg = false, .val ='s' }, {NULL }, };
@@ -36,8 +39,9 @@ static const struct option options[] = {/* Debugging prototype. */ static int for_each_table (int (*func)(const char *tablename)) { -int ret =1 ; +int i, count =0 , ret =1 ;FILE *procfile =NULL ; +char **tables =NULL ;char tablename[XT_TABLE_MAXNAMELEN +1 ]; procfile =fopen ("/proc/net/ip6_tables_names" ,"re" );
@@ -50,10 +54,18 @@ static int for_each_table(int (*func)(const char *tablename))"Badly formed tablename `%s'\n" , tablename); tablename[strlen (tablename) -1 ] ='\0' ; - ret &=func (tablename); + count++; + tables = (char **)realloc (tables,sizeof (char *)*count); + tables[count-1 ] =strdup (tablename); } -fclose (procfile); + +if (sort_tables == true) +qsort (tables, count,sizeof (char *), stringcmp); +for (i =0 ; i < count ; i++) { + ret &=func (tables[i]); + } +return ret; }
@@ -141,7 +153,7 @@ int ip6tables_save_main(int argc, char *argv[])init_extensions6 ();#endif -while ((c =getopt_long (argc, argv,"bcdt:" , options,NULL )) !=-1 ) { +while ((c =getopt_long (argc, argv,"bcdt:s" , options,NULL )) !=-1 ) {switch (c) {case 'c' : show_counters =1 ;
@@ -154,6 +166,9 @@ int ip6tables_save_main(int argc, char *argv[])case 'M' : xtables_modprobe_program = optarg;break ; +case 's' : + sort_tables = true; +break ;case 'd' :do_output (tablename);exit (0 );
iptables/iptables-save.8 +4 -0
@@ -39,6 +39,10 @@ include the current values of all packet and byte counters in the output \fB\-t\fR, \fB\-\-table\fR \fItablename\fP restrict output to only one table. If not specified, output includes all available tables. +.TP +\fB\-s\fR, \fB\-\-sorted\fR +by default, tables are output in LIFO order. This option enables +sorting, and tables are output in alphabetical order. .SH BUGS None known as of iptables-1.2.1 release .SH AUTHOR
iptables/iptables-save.c +19 -4
@@ -9,6 +9,7 @@#include <sys/errno.h> #include <stdio.h> #include <fcntl.h> +#include <stdbool.h> #include <stdlib.h> #include <string.h> #include <time.h>
@@ -22,20 +23,23 @@#endif static int show_counters =0 ; +static bool sort_tables = false;static const struct option options[] = { {.name ="counters" , .has_arg = false, .val ='c' }, {.name ="dump" , .has_arg = false, .val ='d' }, {.name ="table" , .has_arg = true, .val ='t' }, {.name ="modprobe" , .has_arg = true, .val ='M' }, + {.name ="sorted" , .has_arg = false, .val ='s' }, {NULL }, };/* Debugging prototype. */ static int for_each_table (int (*func)(const char *tablename)) { -int ret =1 ; +int i, count =0 , ret =1 ;FILE *procfile =NULL ; +char **tables =NULL ;char tablename[XT_TABLE_MAXNAMELEN +1 ]; procfile =fopen ("/proc/net/ip_tables_names" ,"re" );
@@ -48,10 +52,18 @@ static int for_each_table(int (*func)(const char *tablename))"Badly formed tablename `%s'\n" , tablename); tablename[strlen (tablename) -1 ] ='\0' ; - ret &=func (tablename); + count++; + tables = (char **)realloc (tables,sizeof (char *)*count); + tables[count-1 ] =strdup (tablename); } -fclose (procfile); + +if (sort_tables == true) +qsort (tables, count,sizeof (char *), stringcmp); +for (i =0 ; i < count ; i++) { + ret &=func (tables[i]); + } +return ret; }
@@ -140,7 +152,7 @@ iptables_save_main(int argc, char *argv[])init_extensions4 ();#endif -while ((c =getopt_long (argc, argv,"bcdt:" , options,NULL )) !=-1 ) { +while ((c =getopt_long (argc, argv,"bcdt:s" , options,NULL )) !=-1 ) {switch (c) {case 'c' : show_counters =1 ;
@@ -153,6 +165,9 @@ iptables_save_main(int argc, char *argv[])case 'M' : xtables_modprobe_program = optarg;break ; +case 's' : + sort_tables = true; +break ;case 'd' :do_output (tablename);exit (0 );
libxtables/xtables.c +7 -0
@@ -1961,3 +1961,10 @@ void get_kernel_version(void)sscanf (uts.release,"%d.%d.%d" , &x, &y, &z); kernel_version =LINUX_VERSION (x, y, z); } + +int stringcmp (const void *a,const void *b) +{ +const char **ia = (const char **)a; +const char **ib = (const char **)b; +return strcmp (*ia, *ib); +}
Pablo Neira Ayuso
maintainerHi Phil,
Quoted 7 lines · Phil Oester
Depending upon the load order of rules, the output from ip[6]tables-save will vary, as ip[6]_tables_names is sorted LIFO. As reported by Linus van Geuns, this makes comparing output from ip[6]tables-save across reboots difficult. Attached are two patches which attempt to fix this.
1) Sort by default - add 'u' option to unsort
2) Unsorted by default - add 's' option to sort
I think we should just sorted it inconditionally. I don't get how that can be useful for any interesting purpose.
More comments below:
include/xtables.h extern void xtables_ip6parse_any(const char *, struct in6_addr **, · line 482
Quoted 9 lines
include/xtables.h +1
-0@@ -479,6 +479,8 @@ extern void xtables_ip6parse_any(const char *, struct in6_addr **,extern void xtables_ip6parse_multiple (const char *,struct in6_addr **,struct in6_addr **,unsigned int *); +extern int stringcmp (const void *,const void *);
Please, no new function into libxtables for this. Better define it internally to iptables-save and ip6tables-save.
I also have to ask you to make a patch for iptables-nftables, so we obtain the same behaviour in xtables-save.
Thanks.