Merge branch 'master' into net-next
This commit is contained in:
commit
651dccbee7
|
|
@ -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;
|
||||
|
|
|
|||
105
ip/iprule.c
105
ip/iprule.c
|
|
@ -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) {
|
||||
|
|
|
|||
10
ip/rtm_map.c
10
ip/rtm_map.c
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue