]> git.proxmox.com Git - mirror_iproute2.git/commitdiff
Add ip rule save/restore
authorKirill Tkhai <ktkhai@odin.com>
Tue, 20 Oct 2015 10:41:48 +0000 (13:41 +0300)
committerStephen Hemminger <shemming@brocade.com>
Fri, 23 Oct 2015 06:35:57 +0000 (23:35 -0700)
This patch adds save and restore commands to "ip rule"
similar the same is made in commit f4ff11e3e298 for "ip route".

The feature is useful in checkpoint/restore for container
migration, also it may be helpful in some normal situations.

Signed-off-by: Kirill Tkhai <ktkhai@odin.com>
doc/ip-cref.tex
ip/iprule.c
man/man8/ip-rule.8

index ea147950ff4af1795301db26a1ed937120bf76a0..67094c95b3681dbe5e03d580011aa7ad588a81b7 100644 (file)
@@ -2246,6 +2246,42 @@ Besides that, the host 193.233.7.83 is translated into
 another prefix to look like 192.203.80.144 when talking
 to the outer world.
 
+\subsection{{\tt ip rule save} -- save rules tables}
+\label{IP-RULE-SAVE}
+
+\paragraph{Description:} this command saves the contents of the rules
+tables or the rule(s) selected by some criteria to standard output.
+
+\paragraph{Arguments:} \verb|ip rule save| has the same arguments as
+\verb|ip rule show|.
+
+\paragraph{Example:} This saves all the rules to the {\tt saved\_rules}
+file:
+\begin{verbatim}
+dan@caffeine:~ # ip rule save > saved_rules
+\end{verbatim}
+
+\paragraph{Output format:} The format of the data stream provided by
+\verb|ip rule save| is that of \verb|rtnetlink|.  See
+\verb|rtnetlink(7)| for more information.
+
+\subsection{{\tt ip rule restore} -- restore rules tables}
+\label{IP-RULE-RESTORE}
+
+\paragraph{Description:} this command restores the contents of the rules
+tables according to a data stream as provided by \verb|ip rule save| via
+standard input.  Note that any rules already in the table are left unchanged,
+and duplicates are not ignored.
+
+\paragraph{Arguments:} This command takes no arguments.
+
+\paragraph{Example:} This restores all rules that were saved to the
+{\tt saved\_rules} file:
+
+\begin{verbatim}
+dan@caffeine:~ # ip rule restore < saved_rules
+\end{verbatim}
+
 
 
 \section{{\tt ip maddress} --- multicast addresses management}
index 2fa9ade9bd23baac04c2f4c0c823c1c9cc8d347b..cec292468c45811d140e49aee23eafe21ceae499 100644 (file)
@@ -21,6 +21,7 @@
 #include <arpa/inet.h>
 #include <string.h>
 #include <linux/fib_rules.h>
+#include <errno.h>
 
 #include "rt_names.h"
 #include "utils.h"
@@ -32,7 +33,8 @@ static void usage(void) __attribute__((noreturn));
 
 static void usage(void)
 {
-       fprintf(stderr, "Usage: ip rule [ list | add | del | flush ] SELECTOR ACTION\n");
+       fprintf(stderr, "Usage: ip rule [ list | add | del | flush | save ] SELECTOR ACTION\n");
+       fprintf(stderr, "       ip rule restore\n");
        fprintf(stderr, "SELECTOR := [ not ] [ from PREFIX ] [ to PREFIX ] [ tos TOS ] [ fwmark FWMARK[/MASK] ]\n");
        fprintf(stderr, "            [ iif STRING ] [ oif STRING ] [ pref NUMBER ]\n");
        fprintf(stderr, "ACTION := [ table TABLE_ID ]\n");
@@ -205,24 +207,65 @@ int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
        return 0;
 }
 
-static int iprule_list(int argc, char **argv)
+static __u32 rule_dump_magic = 0x71706986;
+
+static int save_rule_prep(void)
+{
+       int ret;
+
+       if (isatty(STDOUT_FILENO)) {
+               fprintf(stderr, "Not sending a binary stream to stdout\n");
+               return -1;
+       }
+
+       ret = write(STDOUT_FILENO, &rule_dump_magic, sizeof(rule_dump_magic));
+       if (ret != sizeof(rule_dump_magic)) {
+               fprintf(stderr, "Can't write magic to dump file\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+static int save_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 {
+       int ret;
+
+       ret = write(STDOUT_FILENO, n, n->nlmsg_len);
+       if ((ret > 0) && (ret != n->nlmsg_len)) {
+               fprintf(stderr, "Short write while saving nlmsg\n");
+               ret = -EIO;
+       }
+
+       return ret == n->nlmsg_len ? 0 : ret;
+}
+
+static int iprule_list_or_save(int argc, char **argv, int save)
+{
+       rtnl_filter_t filter = print_rule;
        int af = preferred_family;
 
        if (af == AF_UNSPEC)
                af = AF_INET;
 
        if (argc > 0) {
-               fprintf(stderr, "\"ip rule show\" does not take any arguments.\n");
+               fprintf(stderr, "\"ip rule %s\" does not take any arguments.\n",
+                               save ? "save" : "show");
                return -1;
        }
 
+       if (save) {
+               if (save_rule_prep())
+                       return -1;
+               filter = save_rule;
+       }
+
        if (rtnl_wilddump_request(&rth, af, RTM_GETRULE) < 0) {
                perror("Cannot send dump request");
                return 1;
        }
 
-       if (rtnl_dump_filter(&rth, print_rule, stdout) < 0) {
+       if (rtnl_dump_filter(&rth, filter, stdout) < 0) {
                fprintf(stderr, "Dump terminated\n");
                return 1;
        }
@@ -230,6 +273,50 @@ static int iprule_list(int argc, char **argv)
        return 0;
 }
 
+static int rule_dump_check_magic(void)
+{
+       int ret;
+       __u32 magic = 0;
+
+       if (isatty(STDIN_FILENO)) {
+               fprintf(stderr, "Can't restore rule dump from a terminal\n");
+               return -1;
+       }
+
+       ret = fread(&magic, sizeof(magic), 1, stdin);
+       if (magic != rule_dump_magic) {
+               fprintf(stderr, "Magic mismatch (%d elems, %x magic)\n", ret, magic);
+               return -1;
+       }
+
+       return 0;
+}
+
+static int restore_handler(const struct sockaddr_nl *nl,
+                          struct rtnl_ctrl_data *ctrl,
+                          struct nlmsghdr *n, void *arg)
+{
+       int ret;
+
+       n->nlmsg_flags |= NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK;
+
+       ll_init_map(&rth);
+
+       ret = rtnl_talk(&rth, n, n, sizeof(*n));
+       if ((ret < 0) && (errno == EEXIST))
+               ret = 0;
+
+       return ret;
+}
+
+
+static int iprule_restore(void)
+{
+       if (rule_dump_check_magic())
+               exit(-1);
+
+       exit(rtnl_from_file(stdin, &restore_handler, NULL));
+}
 
 static int iprule_modify(int cmd, int argc, char **argv)
 {
@@ -443,11 +530,15 @@ static int iprule_flush(int argc, char **argv)
 int do_iprule(int argc, char **argv)
 {
        if (argc < 1) {
-               return iprule_list(0, NULL);
+               return iprule_list_or_save(0, NULL, 0);
        } else if (matches(argv[0], "list") == 0 ||
                   matches(argv[0], "lst") == 0 ||
                   matches(argv[0], "show") == 0) {
-               return iprule_list(argc-1, argv+1);
+               return iprule_list_or_save(argc-1, argv+1, 0);
+       } else if (matches(argv[0], "save") == 0) {
+               return iprule_list_or_save(argc-1, argv+1, 1);
+       } else if (matches(argv[0], "restore") == 0) {
+               return iprule_restore();
        } else if (matches(argv[0], "add") == 0) {
                return iprule_modify(RTM_NEWRULE, argc-1, argv+1);
        } else if (matches(argv[0], "delete") == 0) {
index 6245d8cf657611868cf29642a3e112bfbf77c783..b1d03e799bdba45c288997a6b596597f9d912e65 100644 (file)
@@ -15,9 +15,12 @@ ip-rule \- routing policy database management
 
 .ti -8
 .B  ip rule
-.RB " [ " list " | " add " | " del " | " flush " ]"
+.RB " [ " list " | " add " | " del " | " flush " | " save " ]"
 .I  SELECTOR ACTION
 
+.ti -8
+.B  ip rule  " restore "
+
 .ti -8
 .IR SELECTOR " := [ "
 .B  from
@@ -265,6 +268,27 @@ This command has no arguments.
 This command has no arguments.
 The options list or lst are synonyms with show.
 
+.TP
+.B ip rule save
+save rules table information to stdout
+.RS
+This command behaves like
+.BR "ip rule show"
+except that the output is raw data suitable for passing to
+.BR "ip rule restore" .
+.RE
+
+.TP
+.B ip rule restore
+restore rules table information from stdin
+.RS
+This command expects to read a data stream as returned from
+.BR "ip rule save" .
+It will attempt to restore the rules table information exactly as
+it was at the time of the save. Any rules already in the table are
+left unchanged, and duplicates are not ignored.
+.RE
+
 .SH SEE ALSO
 .br
 .BR ip (8)