Commit 651dccbe authored by Stephen Hemminger's avatar Stephen Hemminger

Merge branch 'master' into net-next

parents b89c359c d583e88e
......@@ -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}
......
......@@ -160,7 +160,7 @@ struct rtattr {
/* Macros to handle rtattributes */
#define RTA_ALIGNTO 4
#define RTA_ALIGNTO 4U
#define RTA_ALIGN(len) ( ((len)+RTA_ALIGNTO-1) & ~(RTA_ALIGNTO-1) )
#define RTA_OK(rta,len) ((len) >= (int)sizeof(struct rtattr) && \
(rta)->rta_len >= sizeof(struct rtattr) && \
......
......@@ -4,7 +4,6 @@
char *rtnl_rtntype_n2a(int id, char *buf, int len);
int rtnl_rtntype_a2n(int *id, char *arg);
int get_rt_realms(__u32 *realms, char *arg);
int get_rt_realms_or_raw(__u32 *realms, char *arg);
#endif /* __RTM_MAP_H__ */
......@@ -762,7 +762,7 @@ static int parse_one_nh(struct nlmsghdr *n, struct rtmsg *r,
} else if (matches(*argv, "realms") == 0) {
__u32 realm;
NEXT_ARG();
if (get_rt_realms(&realm, *argv))
if (get_rt_realms_or_raw(&realm, *argv))
invarg("\"realm\" value is invalid\n", *argv);
rta_addattr32(rta, 4096, RTA_FLOW, realm);
rtnh->rtnh_len += sizeof(struct rtattr) + 4;
......@@ -1068,7 +1068,7 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
} else if (matches(*argv, "realms") == 0) {
__u32 realm;
NEXT_ARG();
if (get_rt_realms(&realm, *argv))
if (get_rt_realms_or_raw(&realm, *argv))
invarg("\"realm\" value is invalid\n", *argv);
addattr32(&req.n, sizeof(req), RTA_FLOW, realm);
} else if (strcmp(*argv, "onlink") == 0) {
......@@ -1412,7 +1412,7 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
} else if (matches(*argv, "realms") == 0) {
__u32 realm;
NEXT_ARG();
if (get_rt_realms(&realm, *argv))
if (get_rt_realms_or_raw(&realm, *argv))
invarg("invalid realms\n", *argv);
filter.realm = realm;
filter.realmmask = ~0U;
......
......@@ -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)
{
......@@ -304,7 +391,7 @@ static int iprule_modify(int cmd, int argc, char **argv)
} else if (matches(*argv, "realms") == 0) {
__u32 realm;
NEXT_ARG();
if (get_rt_realms(&realm, *argv))
if (get_rt_realms_or_raw(&realm, *argv))
invarg("invalid realms\n", *argv);
addattr32(&req.n, sizeof(req), FRA_FLOW, realm);
} else if (matches(*argv, "table") == 0 ||
......@@ -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) {
......
......@@ -93,7 +93,7 @@ int rtnl_rtntype_a2n(int *id, char *arg)
return 0;
}
int get_rt_realms(__u32 *realms, char *arg)
static int get_rt_realms(__u32 *realms, char *arg)
{
__u32 realm = 0;
char *p = strchr(arg, '/');
......@@ -114,3 +114,11 @@ int get_rt_realms(__u32 *realms, char *arg)
*realms |= realm;
return 0;
}
int get_rt_realms_or_raw(__u32 *realms, char *arg)
{
if (!get_rt_realms(realms, arg))
return 0;
return get_unsigned(realms, arg, 0);
}
......@@ -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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment