netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] iproute: Add magic cookie to route dump file
@ 2012-07-27  4:55 Pavel Emelyanov
  2012-07-27  4:57 ` [PATCH 2/2] iproute: Add route showdump command (v2) Pavel Emelyanov
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Pavel Emelyanov @ 2012-07-27  4:55 UTC (permalink / raw)
  To: Stephen Hemminger, Linux Netdev List

In order to somehow verify that a blob contains route dump a
4-bytes magic is put at the head of the data and is checked
on restore.

Magic digits are taken from Portland (OR) coordinates :) Is
there any more reliable way of generating such?

Signed-of-by: Pavel Emelyanov <xemul@parallels.com>

---

 ip/iproute.c |   54 +++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 47 insertions(+), 7 deletions(-)

diff --git a/ip/iproute.c b/ip/iproute.c
index 5cd313e..bbb3923 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -1064,6 +1064,8 @@ static int iproute_flush_cache(void)
 	return 0;
 }
 
+static __u32 route_dump_magic = 0x45311224;
+
 int save_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 {
 	int ret;
@@ -1072,11 +1074,6 @@ int save_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 	struct rtattr *tb[RTA_MAX+1];
 	int host_len = -1;
 
-	if (isatty(STDOUT_FILENO)) {
-		fprintf(stderr, "Not sending binary stream to stdout\n");
-		return -1;
-	}
-
 	host_len = calc_host_len(r);
 	len -= NLMSG_LENGTH(sizeof(*r));
 	parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
@@ -1093,6 +1090,24 @@ int save_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 	return ret == n->nlmsg_len ? 0 : ret;
 }
 
+static int save_route_prep(void)
+{
+	int ret;
+
+	if (isatty(STDOUT_FILENO)) {
+		fprintf(stderr, "Not sending binary stream to stdout\n");
+		return -1;
+	}
+
+	ret = write(STDOUT_FILENO, &route_dump_magic, sizeof(route_dump_magic));
+	if (ret != sizeof(route_dump_magic)) {
+		fprintf(stderr, "Can't write magic to dump file\n");
+		return -1;
+	}
+
+	return 0;
+}
+
 static int iproute_list_flush_or_save(int argc, char **argv, int action)
 {
 	int do_ipv6 = preferred_family;
@@ -1101,9 +1116,12 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
 	unsigned int mark = 0;
 	rtnl_filter_t filter_fn;
 
-	if (action == IPROUTE_SAVE)
+	if (action == IPROUTE_SAVE) {
+		if (save_route_prep())
+			return -1;
+
 		filter_fn = save_route;
-	else
+	} else
 		filter_fn = print_route;
 
 	iproute_reset_filter();
@@ -1521,8 +1539,30 @@ int restore_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n, void *arg)
 	return ret;
 }
 
+static int route_dump_check_magic(void)
+{
+	int ret;
+	__u32 magic = 0;
+
+	if (isatty(STDIN_FILENO)) {
+		fprintf(stderr, "Can't restore route dump from a terminal\n");
+		return -1;
+	}
+
+	ret = fread(&magic, sizeof(magic), 1, stdin);
+	if (magic != route_dump_magic) {
+		fprintf(stderr, "Magic mismatch (%d elems, %x magic)\n", ret, magic);
+		return -1;
+	}
+
+	return 0;
+}
+
 int iproute_restore(void)
 {
+	if (route_dump_check_magic())
+		exit(-1);
+
 	exit(rtnl_from_file(stdin, &restore_handler, NULL));
 }
 
-- 
1.5.5.6

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 2/2] iproute: Add route showdump command (v2)
  2012-07-27  4:55 [PATCH 1/2] iproute: Add magic cookie to route dump file Pavel Emelyanov
@ 2012-07-27  4:57 ` Pavel Emelyanov
  2012-07-27  5:03   ` Pavel Emelyanov
  2012-09-07 16:14   ` [PATCH 2/2] iproute: Add route showdump command (v2) Stephen Hemminger
  2012-07-27 10:46 ` [PATCH 1/2] iproute: Add magic cookie to route dump file David Laight
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 13+ messages in thread
From: Pavel Emelyanov @ 2012-07-27  4:57 UTC (permalink / raw)
  To: Stephen Hemminger, Linux Netdev List

Some time ago the save+restore commands were added to ip route (git
id f4ff11e3, Add ip route save/restore). These two save the raw rtnl
stream into a file and restore one (reading it from stdin).

The problem is that there's no way to get the contents of the dump
file in a human readable form. The proposal is to add a command that
reads the rtnl stream from stdin and prints the data in a way the 
usual "ip route list" does?

changes since v1:

* Take the magic at the beginning of the dump file into account
* Check for stdin (the dump is taken from) is not a tty

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>

---

 ip/iproute.c |   17 +++++++++++++++++
 1 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/ip/iproute.c b/ip/iproute.c
index bbb3923..572e2e8 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -60,6 +60,7 @@ static void usage(void)
 	fprintf(stderr, "Usage: ip route { list | flush } SELECTOR\n");
 	fprintf(stderr, "       ip route save SELECTOR\n");
 	fprintf(stderr, "       ip route restore\n");
+	fprintf(stderr, "       ip route showdump\n");
 	fprintf(stderr, "       ip route get ADDRESS [ from ADDRESS iif STRING ]\n");
 	fprintf(stderr, "                            [ oif STRING ]  [ tos TOS ]\n");
 	fprintf(stderr, "                            [ mark NUMBER ]\n");
@@ -1566,6 +1567,20 @@ int iproute_restore(void)
 	exit(rtnl_from_file(stdin, &restore_handler, NULL));
 }
 
+static int show_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n, void *arg)
+{
+	print_route(nl, n, stdout);
+	return 0;
+}
+
+static int iproute_showdump(void)
+{
+	if (route_dump_check_magic())
+		exit(-1);
+
+	exit(rtnl_from_file(stdin, &show_handler, NULL));
+}
+
 void iproute_reset_filter()
 {
 	memset(&filter, 0, sizeof(filter));
@@ -1610,6 +1625,8 @@ int do_iproute(int argc, char **argv)
 		return iproute_list_flush_or_save(argc-1, argv+1, IPROUTE_SAVE);
 	if (matches(*argv, "restore") == 0)
 		return iproute_restore();
+	if (matches(*argv, "showdump") == 0)
+		return iproute_showdump();
 	if (matches(*argv, "help") == 0)
 		usage();
 	fprintf(stderr, "Command \"%s\" is unknown, try \"ip route help\".\n", *argv);
-- 
1.5.5.6

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/2] iproute: Add route showdump command (v2)
  2012-07-27  4:57 ` [PATCH 2/2] iproute: Add route showdump command (v2) Pavel Emelyanov
@ 2012-07-27  5:03   ` Pavel Emelyanov
  2012-07-27  6:06     ` Pavel Emelyanov
  2012-09-11 15:47     ` [PATCH] iproute: Add ability to save, restore and show the interfaces' addresses (resend) Pavel Emelyanov
  2012-09-07 16:14   ` [PATCH 2/2] iproute: Add route showdump command (v2) Stephen Hemminger
  1 sibling, 2 replies; 13+ messages in thread
From: Pavel Emelyanov @ 2012-07-27  5:03 UTC (permalink / raw)
  To: Stephen Hemminger, Linux Netdev List

Stephen, I have a question regarding the save and restore in iproute tool.

As you know, the save/restore pair for routes works in a very simple and
elegant manner -- on save the raw kernel rtnl stream is just put into a
file, on restore the _very_ _same_ messages are pushed back to the kernel.

Is the same trick possible to save and restore the addresses (the ip
addr command) as well? Or the RTM_GETADDR messages cannot be just read
from and written back to the network stack in a generic case?

Thanks,
Pavel

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/2] iproute: Add route showdump command (v2)
  2012-07-27  5:03   ` Pavel Emelyanov
@ 2012-07-27  6:06     ` Pavel Emelyanov
  2012-07-27 17:05       ` Stephen Hemminger
  2012-09-11 15:47     ` [PATCH] iproute: Add ability to save, restore and show the interfaces' addresses (resend) Pavel Emelyanov
  1 sibling, 1 reply; 13+ messages in thread
From: Pavel Emelyanov @ 2012-07-27  6:06 UTC (permalink / raw)
  To: Stephen Hemminger, Linux Netdev List

On 07/27/2012 09:03 AM, Pavel Emelyanov wrote:
> As you know, the save/restore pair for routes works in a very simple and
> elegant manner -- on save the raw kernel rtnl stream is just put into a
> file, on restore the _very_ _same_ messages are pushed back to the kernel.
> 
> Is the same trick possible to save and restore the addresses (the ip
> addr command) as well? Or the RTM_GETADDR messages cannot be just read
> from and written back to the network stack in a generic case?

I mean something like the below, just put the RTM_GETADDR stream into a
file and push it back into the kernel as is. It worked for me in trivial
cases, but is this approach correct generically?

Log:

iproute: Add ability to save, restore and show the interfaces' addresses

Implementation is similar to the ip route {save|restore|showdump} one.

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>

---

diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 37deda5..6788544 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -34,6 +34,11 @@
 #include "ll_map.h"
 #include "ip_common.h"
 
+enum {
+	IPADD_LIST,
+	IPADD_FLUSH,
+	IPADD_SAVE,
+};
 
 static struct
 {
@@ -65,8 +70,9 @@ static void usage(void)
 	fprintf(stderr, "Usage: ip addr {add|change|replace} IFADDR dev STRING [ LIFETIME ]\n");
 	fprintf(stderr, "                                                      [ CONFFLAG-LIST ]\n");
 	fprintf(stderr, "       ip addr del IFADDR dev STRING\n");
-	fprintf(stderr, "       ip addr {show|flush} [ dev STRING ] [ scope SCOPE-ID ]\n");
+	fprintf(stderr, "       ip addr {show|save|flush} [ dev STRING ] [ scope SCOPE-ID ]\n");
 	fprintf(stderr, "                            [ to PREFIX ] [ FLAG-LIST ] [ label PATTERN ]\n");
+	fprintf(stderr, "       ip addr {showdump|restore}\n");
 	fprintf(stderr, "IFADDR := PREFIX | ADDR peer PREFIX\n");
 	fprintf(stderr, "          [ broadcast ADDR ] [ anycast ADDR ]\n");
 	fprintf(stderr, "          [ label STRING ] [ scope SCOPE-ID ]\n");
@@ -768,6 +774,99 @@ static int store_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n,
 	return 0;
 }
 
+static __u32 ipadd_dump_magic = 0x47361222;
+
+static int ipadd_save_prep(void)
+{
+	int ret;
+
+	if (isatty(STDOUT_FILENO)) {
+		fprintf(stderr, "Not sending binary stream to stdout\n");
+		return -1;
+	}
+
+	ret = write(STDOUT_FILENO, &ipadd_dump_magic, sizeof(ipadd_dump_magic));
+	if (ret != sizeof(ipadd_dump_magic)) {
+		fprintf(stderr, "Can't write magic to dump file\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int ipadd_dump_check_magic(void)
+{
+	int ret;
+	__u32 magic = 0;
+
+	if (isatty(STDIN_FILENO)) {
+		fprintf(stderr, "Can't restore addr dump from a terminal\n");
+		return -1;
+	}
+
+	ret = fread(&magic, sizeof(magic), 1, stdin);
+	if (magic != ipadd_dump_magic) {
+		fprintf(stderr, "Magic mismatch (%d elems, %x magic)\n", ret, magic);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int save_nlmsg(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 show_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n, void *arg)
+{
+	struct ifaddrmsg *ifa = NLMSG_DATA(n);
+
+	printf("if%d:\n", ifa->ifa_index);
+	print_addrinfo(NULL, n, stdout);
+	return 0;
+}
+
+static int ipaddr_showdump(void)
+{
+	if (ipadd_dump_check_magic())
+		exit(-1);
+
+	exit(rtnl_from_file(stdin, &show_handler, NULL));
+}
+
+static int restore_handler(const struct sockaddr_nl *nl, 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, 0, 0, n);
+	if ((ret < 0) && (errno == EEXIST))
+		ret = 0;
+
+	return ret;
+}
+
+static int ipaddr_restore(void)
+{
+	if (ipadd_dump_check_magic())
+		exit(-1);
+
+	exit(rtnl_from_file(stdin, &restore_handler, NULL));
+}
+
 static void free_nlmsg_chain(struct nlmsg_chain *info)
 {
 	struct nlmsg_list *l, *n;
@@ -902,7 +1001,7 @@ static int ipaddr_flush(void)
 	return 1;
 }
 
-static int ipaddr_list_or_flush(int argc, char **argv, int flush)
+static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
 {
 	struct nlmsg_chain linfo = { NULL, NULL};
 	struct nlmsg_chain ainfo = { NULL, NULL};
@@ -918,7 +1017,7 @@ static int ipaddr_list_or_flush(int argc, char **argv, int flush)
 
 	filter.group = INIT_NETDEV_GROUP;
 
-	if (flush) {
+	if (action == IPADD_FLUSH) {
 		if (argc <= 0) {
 			fprintf(stderr, "Flush requires arguments.\n");
 
@@ -1005,9 +1104,26 @@ static int ipaddr_list_or_flush(int argc, char **argv, int flush)
 		}
 	}
 
-	if (flush)
+	if (action == IPADD_FLUSH)
 		return ipaddr_flush();
 
+	if (action == IPADD_SAVE) {
+		if (ipadd_save_prep())
+			exit(1);
+
+		if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETADDR) < 0) {
+			perror("Cannot send dump request");
+			exit(1);
+		}
+
+		if (rtnl_dump_filter(&rth, save_nlmsg, stdout) < 0) {
+			fprintf(stderr, "Save terminated\n");
+			exit(1);
+		}
+
+		exit(0);
+	}
+
 	if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK) < 0) {
 		perror("Cannot send dump request");
 		exit(1);
@@ -1055,7 +1171,7 @@ int ipaddr_list_link(int argc, char **argv)
 {
 	preferred_family = AF_PACKET;
 	do_link = 1;
-	return ipaddr_list_or_flush(argc, argv, 0);
+	return ipaddr_list_flush_or_save(argc, argv, IPADD_LIST);
 }
 
 void ipaddr_reset_filter(int oneline)
@@ -1271,7 +1387,7 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
 int do_ipaddr(int argc, char **argv)
 {
 	if (argc < 1)
-		return ipaddr_list_or_flush(0, NULL, 0);
+		return ipaddr_list_flush_or_save(0, NULL, IPADD_LIST);
 	if (matches(*argv, "add") == 0)
 		return ipaddr_modify(RTM_NEWADDR, NLM_F_CREATE|NLM_F_EXCL, argc-1, argv+1);
 	if (matches(*argv, "change") == 0 ||
@@ -1283,9 +1399,15 @@ int do_ipaddr(int argc, char **argv)
 		return ipaddr_modify(RTM_DELADDR, 0, argc-1, argv+1);
 	if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0
 	    || matches(*argv, "lst") == 0)
-		return ipaddr_list_or_flush(argc-1, argv+1, 0);
+		return ipaddr_list_flush_or_save(argc-1, argv+1, IPADD_LIST);
 	if (matches(*argv, "flush") == 0)
-		return ipaddr_list_or_flush(argc-1, argv+1, 1);
+		return ipaddr_list_flush_or_save(argc-1, argv+1, IPADD_FLUSH);
+	if (matches(*argv, "save") == 0)
+		return ipaddr_list_flush_or_save(argc-1, argv+1, IPADD_SAVE);
+	if (matches(*argv, "showdump") == 0)
+		return ipaddr_showdump();
+	if (matches(*argv, "restore") == 0)
+		return ipaddr_restore();
 	if (matches(*argv, "help") == 0)
 		usage();
 	fprintf(stderr, "Command \"%s\" is unknown, try \"ip addr help\".\n", *argv);

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* RE: [PATCH 1/2] iproute: Add magic cookie to route dump file
  2012-07-27  4:55 [PATCH 1/2] iproute: Add magic cookie to route dump file Pavel Emelyanov
  2012-07-27  4:57 ` [PATCH 2/2] iproute: Add route showdump command (v2) Pavel Emelyanov
@ 2012-07-27 10:46 ` David Laight
  2012-07-27 13:35   ` Pavel Emelyanov
  2012-07-27 16:59 ` Stephen Hemminger
  2012-08-17 20:49 ` Stephen Hemminger
  3 siblings, 1 reply; 13+ messages in thread
From: David Laight @ 2012-07-27 10:46 UTC (permalink / raw)
  To: Pavel Emelyanov, Stephen Hemminger, Linux Netdev List

> In order to somehow verify that a blob contains route dump a
> 4-bytes magic is put at the head of the data and is checked
> on restore.

Wouldn't a hash/checksum be useful as well?
Especially if it uneditable data.

	David

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/2] iproute: Add magic cookie to route dump file
  2012-07-27 10:46 ` [PATCH 1/2] iproute: Add magic cookie to route dump file David Laight
@ 2012-07-27 13:35   ` Pavel Emelyanov
  0 siblings, 0 replies; 13+ messages in thread
From: Pavel Emelyanov @ 2012-07-27 13:35 UTC (permalink / raw)
  To: David Laight; +Cc: Stephen Hemminger, Linux Netdev List

On 07/27/2012 02:46 PM, David Laight wrote:
>> In order to somehow verify that a blob contains route dump a
>> 4-bytes magic is put at the head of the data and is checked
>> on restore.
> 
> Wouldn't a hash/checksum be useful as well?

I doubt it. This magic is not for data integrity check, but is
rather for identification of it. Is someone really needs a cheksum
of a dump, it can be added after file generation (and by the
preferred tool, not limited with the iproute implementation).

> Especially if it uneditable data.
> 
> 	David
> 
> 
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/2] iproute: Add magic cookie to route dump file
  2012-07-27  4:55 [PATCH 1/2] iproute: Add magic cookie to route dump file Pavel Emelyanov
  2012-07-27  4:57 ` [PATCH 2/2] iproute: Add route showdump command (v2) Pavel Emelyanov
  2012-07-27 10:46 ` [PATCH 1/2] iproute: Add magic cookie to route dump file David Laight
@ 2012-07-27 16:59 ` Stephen Hemminger
  2012-08-17 20:49 ` Stephen Hemminger
  3 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2012-07-27 16:59 UTC (permalink / raw)
  To: Pavel Emelyanov; +Cc: Stephen Hemminger, Linux Netdev List

On Fri, 27 Jul 2012 08:55:41 +0400
Pavel Emelyanov <xemul@parallels.com> wrote:

> In order to somehow verify that a blob contains route dump a
> 4-bytes magic is put at the head of the data and is checked
> on restore.
> 
> Magic digits are taken from Portland (OR) coordinates :) Is
> there any more reliable way of generating such?
> 
> Signed-of-by: Pavel Emelyanov <xemul@parallels.com>
> 

Any magic number is fine as long as it is non-offensive and
unique.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/2] iproute: Add route showdump command (v2)
  2012-07-27  6:06     ` Pavel Emelyanov
@ 2012-07-27 17:05       ` Stephen Hemminger
  0 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2012-07-27 17:05 UTC (permalink / raw)
  To: Pavel Emelyanov; +Cc: Stephen Hemminger, Linux Netdev List

On Fri, 27 Jul 2012 10:06:15 +0400
Pavel Emelyanov <xemul@parallels.com> wrote:

> I mean something like the below, just put the RTM_GETADDR stream into a
> file and push it back into the kernel as is. It worked for me in trivial
> cases, but is this approach correct generically?

It is supposed to always work to reverse netlink messages back to the kernel.
There a couple of caveats:
 1. Some fields like statistics are just ignored by the kernel and can never
    be reset.
 2. The feature isn't commonly used and it is always possible that it will
    expose a kernel bug.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/2] iproute: Add magic cookie to route dump file
  2012-07-27  4:55 [PATCH 1/2] iproute: Add magic cookie to route dump file Pavel Emelyanov
                   ` (2 preceding siblings ...)
  2012-07-27 16:59 ` Stephen Hemminger
@ 2012-08-17 20:49 ` Stephen Hemminger
  2012-08-20  8:05   ` Pavel Emelyanov
  3 siblings, 1 reply; 13+ messages in thread
From: Stephen Hemminger @ 2012-08-17 20:49 UTC (permalink / raw)
  To: Pavel Emelyanov; +Cc: Stephen Hemminger, Linux Netdev List

On Fri, 27 Jul 2012 08:55:41 +0400
Pavel Emelyanov <xemul@parallels.com> wrote:

> In order to somehow verify that a blob contains route dump a
> 4-bytes magic is put at the head of the data and is checked
> on restore.
> 
> Magic digits are taken from Portland (OR) coordinates :) Is
> there any more reliable way of generating such?
> 
> Signed-of-by: Pavel Emelyanov <xemul@parallels.com>

I am planning on putting this in because there were no objections.
Any followup updates?

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/2] iproute: Add magic cookie to route dump file
  2012-08-17 20:49 ` Stephen Hemminger
@ 2012-08-20  8:05   ` Pavel Emelyanov
  0 siblings, 0 replies; 13+ messages in thread
From: Pavel Emelyanov @ 2012-08-20  8:05 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: Stephen Hemminger, Linux Netdev List

On 08/18/2012 12:49 AM, Stephen Hemminger wrote:
> On Fri, 27 Jul 2012 08:55:41 +0400
> Pavel Emelyanov <xemul@parallels.com> wrote:
> 
>> In order to somehow verify that a blob contains route dump a
>> 4-bytes magic is put at the head of the data and is checked
>> on restore.
>>
>> Magic digits are taken from Portland (OR) coordinates :) Is
>> there any more reliable way of generating such?
>>
>> Signed-of-by: Pavel Emelyanov <xemul@parallels.com>
> 
> I am planning on putting this in because there were no objections.
> Any followup updates?

Yes, I've recently found that errno propagation from rtnl_talk up to
addrs/routes restore doesn't work on some libc-s. I will post a fixing
patch soon.

Thanks,
Pavel

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/2] iproute: Add route showdump command (v2)
  2012-07-27  4:57 ` [PATCH 2/2] iproute: Add route showdump command (v2) Pavel Emelyanov
  2012-07-27  5:03   ` Pavel Emelyanov
@ 2012-09-07 16:14   ` Stephen Hemminger
  1 sibling, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2012-09-07 16:14 UTC (permalink / raw)
  To: Pavel Emelyanov; +Cc: Stephen Hemminger, Linux Netdev List

On Fri, 27 Jul 2012 08:57:20 +0400
Pavel Emelyanov <xemul@parallels.com> wrote:

> Some time ago the save+restore commands were added to ip route (git
> id f4ff11e3, Add ip route save/restore). These two save the raw rtnl
> stream into a file and restore one (reading it from stdin).
> 
> The problem is that there's no way to get the contents of the dump
> file in a human readable form. The proposal is to add a command that
> reads the rtnl stream from stdin and prints the data in a way the 
> usual "ip route list" does?
> 
> changes since v1:
> 
> * Take the magic at the beginning of the dump file into account
> * Check for stdin (the dump is taken from) is not a tty
> 
> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>

Applied this and the magic number change.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH] iproute: Add ability to save, restore and show the interfaces' addresses (resend)
  2012-07-27  5:03   ` Pavel Emelyanov
  2012-07-27  6:06     ` Pavel Emelyanov
@ 2012-09-11 15:47     ` Pavel Emelyanov
  2012-09-11 16:18       ` Stephen Hemminger
  1 sibling, 1 reply; 13+ messages in thread
From: Pavel Emelyanov @ 2012-09-11 15:47 UTC (permalink / raw)
  To: Stephen Hemminger, Linux Netdev List

This functionality is required by checkpoint-restore project. Since the
dump and restore for routes is already done in ip tool it's naturally to
dump and restore addresses in the ip tool as well.

The implementation logic is the same as for the respective one for routes.
The magic number digits are taken from the Seattle coordinates.

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>

---

diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index cbff143..6c11ce4 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -34,6 +34,11 @@
 #include "ll_map.h"
 #include "ip_common.h"
 
+enum {
+	IPADD_LIST,
+	IPADD_FLUSH,
+	IPADD_SAVE,
+};
 
 static struct
 {
@@ -65,8 +70,9 @@ static void usage(void)
 	fprintf(stderr, "Usage: ip addr {add|change|replace} IFADDR dev STRING [ LIFETIME ]\n");
 	fprintf(stderr, "                                                      [ CONFFLAG-LIST ]\n");
 	fprintf(stderr, "       ip addr del IFADDR dev STRING\n");
-	fprintf(stderr, "       ip addr {show|flush} [ dev STRING ] [ scope SCOPE-ID ]\n");
+	fprintf(stderr, "       ip addr {show|save|flush} [ dev STRING ] [ scope SCOPE-ID ]\n");
 	fprintf(stderr, "                            [ to PREFIX ] [ FLAG-LIST ] [ label PATTERN ]\n");
+	fprintf(stderr, "       ip addr {showdump|restore}\n");
 	fprintf(stderr, "IFADDR := PREFIX | ADDR peer PREFIX\n");
 	fprintf(stderr, "          [ broadcast ADDR ] [ anycast ADDR ]\n");
 	fprintf(stderr, "          [ label STRING ] [ scope SCOPE-ID ]\n");
@@ -768,6 +774,99 @@ static int store_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n,
 	return 0;
 }
 
+static __u32 ipadd_dump_magic = 0x47361222;
+
+static int ipadd_save_prep(void)
+{
+	int ret;
+
+	if (isatty(STDOUT_FILENO)) {
+		fprintf(stderr, "Not sending binary stream to stdout\n");
+		return -1;
+	}
+
+	ret = write(STDOUT_FILENO, &ipadd_dump_magic, sizeof(ipadd_dump_magic));
+	if (ret != sizeof(ipadd_dump_magic)) {
+		fprintf(stderr, "Can't write magic to dump file\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int ipadd_dump_check_magic(void)
+{
+	int ret;
+	__u32 magic = 0;
+
+	if (isatty(STDIN_FILENO)) {
+		fprintf(stderr, "Can't restore addr dump from a terminal\n");
+		return -1;
+	}
+
+	ret = fread(&magic, sizeof(magic), 1, stdin);
+	if (magic != ipadd_dump_magic) {
+		fprintf(stderr, "Magic mismatch (%d elems, %x magic)\n", ret, magic);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int save_nlmsg(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 show_handler(const struct sockaddr_nl *nl, struct nlmsghdr *n, void *arg)
+{
+	struct ifaddrmsg *ifa = NLMSG_DATA(n);
+
+	printf("if%d:\n", ifa->ifa_index);
+	print_addrinfo(NULL, n, stdout);
+	return 0;
+}
+
+static int ipaddr_showdump(void)
+{
+	if (ipadd_dump_check_magic())
+		exit(-1);
+
+	exit(rtnl_from_file(stdin, &show_handler, NULL));
+}
+
+static int restore_handler(const struct sockaddr_nl *nl, 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, 0, 0, n);
+	if ((ret < 0) && (errno == EEXIST))
+		ret = 0;
+
+	return ret;
+}
+
+static int ipaddr_restore(void)
+{
+	if (ipadd_dump_check_magic())
+		exit(-1);
+
+	exit(rtnl_from_file(stdin, &restore_handler, NULL));
+}
+
 static void free_nlmsg_chain(struct nlmsg_chain *info)
 {
 	struct nlmsg_list *l, *n;
@@ -902,7 +1001,7 @@ static int ipaddr_flush(void)
 	return 1;
 }
 
-static int ipaddr_list_or_flush(int argc, char **argv, int flush)
+static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
 {
 	struct nlmsg_chain linfo = { NULL, NULL};
 	struct nlmsg_chain ainfo = { NULL, NULL};
@@ -918,7 +1017,7 @@ static int ipaddr_list_or_flush(int argc, char **argv, int flush)
 
 	filter.group = INIT_NETDEV_GROUP;
 
-	if (flush) {
+	if (action == IPADD_FLUSH) {
 		if (argc <= 0) {
 			fprintf(stderr, "Flush requires arguments.\n");
 
@@ -1005,9 +1104,26 @@ static int ipaddr_list_or_flush(int argc, char **argv, int flush)
 		}
 	}
 
-	if (flush)
+	if (action == IPADD_FLUSH)
 		return ipaddr_flush();
 
+	if (action == IPADD_SAVE) {
+		if (ipadd_save_prep())
+			exit(1);
+
+		if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETADDR) < 0) {
+			perror("Cannot send dump request");
+			exit(1);
+		}
+
+		if (rtnl_dump_filter(&rth, save_nlmsg, stdout) < 0) {
+			fprintf(stderr, "Save terminated\n");
+			exit(1);
+		}
+
+		exit(0);
+	}
+
 	if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK) < 0) {
 		perror("Cannot send dump request");
 		exit(1);
@@ -1055,7 +1171,7 @@ int ipaddr_list_link(int argc, char **argv)
 {
 	preferred_family = AF_PACKET;
 	do_link = 1;
-	return ipaddr_list_or_flush(argc, argv, 0);
+	return ipaddr_list_flush_or_save(argc, argv, IPADD_LIST);
 }
 
 void ipaddr_reset_filter(int oneline)
@@ -1271,7 +1387,7 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
 int do_ipaddr(int argc, char **argv)
 {
 	if (argc < 1)
-		return ipaddr_list_or_flush(0, NULL, 0);
+		return ipaddr_list_flush_or_save(0, NULL, IPADD_LIST);
 	if (matches(*argv, "add") == 0)
 		return ipaddr_modify(RTM_NEWADDR, NLM_F_CREATE|NLM_F_EXCL, argc-1, argv+1);
 	if (matches(*argv, "change") == 0 ||
@@ -1283,9 +1399,15 @@ int do_ipaddr(int argc, char **argv)
 		return ipaddr_modify(RTM_DELADDR, 0, argc-1, argv+1);
 	if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0
 	    || matches(*argv, "lst") == 0)
-		return ipaddr_list_or_flush(argc-1, argv+1, 0);
+		return ipaddr_list_flush_or_save(argc-1, argv+1, IPADD_LIST);
 	if (matches(*argv, "flush") == 0)
-		return ipaddr_list_or_flush(argc-1, argv+1, 1);
+		return ipaddr_list_flush_or_save(argc-1, argv+1, IPADD_FLUSH);
+	if (matches(*argv, "save") == 0)
+		return ipaddr_list_flush_or_save(argc-1, argv+1, IPADD_SAVE);
+	if (matches(*argv, "showdump") == 0)
+		return ipaddr_showdump();
+	if (matches(*argv, "restore") == 0)
+		return ipaddr_restore();
 	if (matches(*argv, "help") == 0)
 		usage();
 	fprintf(stderr, "Command \"%s\" is unknown, try \"ip addr help\".\n", *argv);

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH] iproute: Add ability to save, restore and show the interfaces' addresses (resend)
  2012-09-11 15:47     ` [PATCH] iproute: Add ability to save, restore and show the interfaces' addresses (resend) Pavel Emelyanov
@ 2012-09-11 16:18       ` Stephen Hemminger
  0 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2012-09-11 16:18 UTC (permalink / raw)
  To: Pavel Emelyanov; +Cc: Stephen Hemminger, Linux Netdev List

On Tue, 11 Sep 2012 19:47:00 +0400
Pavel Emelyanov <xemul@parallels.com> wrote:

> This functionality is required by checkpoint-restore project. Since the
> dump and restore for routes is already done in ip tool it's naturally to
> dump and restore addresses in the ip tool as well.
> 
> The implementation logic is the same as for the respective one for routes.
> The magic number digits are taken from the Seattle coordinates.
> 
> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>

Applied.

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2012-09-11 16:19 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-07-27  4:55 [PATCH 1/2] iproute: Add magic cookie to route dump file Pavel Emelyanov
2012-07-27  4:57 ` [PATCH 2/2] iproute: Add route showdump command (v2) Pavel Emelyanov
2012-07-27  5:03   ` Pavel Emelyanov
2012-07-27  6:06     ` Pavel Emelyanov
2012-07-27 17:05       ` Stephen Hemminger
2012-09-11 15:47     ` [PATCH] iproute: Add ability to save, restore and show the interfaces' addresses (resend) Pavel Emelyanov
2012-09-11 16:18       ` Stephen Hemminger
2012-09-07 16:14   ` [PATCH 2/2] iproute: Add route showdump command (v2) Stephen Hemminger
2012-07-27 10:46 ` [PATCH 1/2] iproute: Add magic cookie to route dump file David Laight
2012-07-27 13:35   ` Pavel Emelyanov
2012-07-27 16:59 ` Stephen Hemminger
2012-08-17 20:49 ` Stephen Hemminger
2012-08-20  8:05   ` Pavel Emelyanov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).