Add ip rule flush capabilty and fix all the prototype changes
because of that code rewrites the nlmsghdr.

(Logical change 1.106)
diff --git a/ChangeLog b/ChangeLog
index 5d5476b..c9c6f1f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2004-12-07  Stephen Hemminger  <shemminger@osdl.org>
+
+	* Cleanup warning generated because ip_rule_flush needs to modify
+	  the netlink message
+
+2004-12-07  Sven Anders <anders@anduras.de>
+
+	* Add ip rule flush
+
 2004-10-19  Harald Welte <laforge@gnumonks.org>
 
 	* Replace rtstat (and ctstat) with new lnstat
diff --git a/include/libnetlink.h b/include/libnetlink.h
index 3390d8b..08be752 100644
--- a/include/libnetlink.h
+++ b/include/libnetlink.h
@@ -20,7 +20,8 @@
 extern int rtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type);
 extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len);
 
-typedef int (*rtnl_filter_t)(const struct sockaddr_nl *, const struct nlmsghdr *n, void *);
+typedef int (*rtnl_filter_t)(const struct sockaddr_nl *, 
+			     struct nlmsghdr *n, void *);
 extern int rtnl_dump_filter(struct rtnl_handle *rth, rtnl_filter_t filter,
 			    void *arg1,
 			    rtnl_filter_t junk,
diff --git a/include/ll_map.h b/include/ll_map.h
index 238a728..3bff5e9 100644
--- a/include/ll_map.h
+++ b/include/ll_map.h
@@ -1,8 +1,8 @@
 #ifndef __LL_MAP_H__
 #define __LL_MAP_H__ 1
 
-extern int ll_remember_index(const struct sockaddr_nl *who, const struct nlmsghdr *n,
-			     void *arg);
+extern int ll_remember_index(const struct sockaddr_nl *who, 
+			     struct nlmsghdr *n, void *arg);
 extern int ll_init_map(struct rtnl_handle *rth);
 extern int ll_name_to_index(const char *name);
 extern const char *ll_index_to_name(int idx);
diff --git a/ip/ip_common.h b/ip/ip_common.h
index c359911..93ac3f9 100644
--- a/ip/ip_common.h
+++ b/ip/ip_common.h
@@ -1,11 +1,11 @@
 extern int print_linkinfo(const struct sockaddr_nl *who, 
-			  const struct nlmsghdr *n, 
+			  struct nlmsghdr *n, 
 			  void *arg);
 extern int print_addrinfo(const struct sockaddr_nl *who,
-			  const struct nlmsghdr *n, 
+			  struct nlmsghdr *n, 
 			  void *arg);
 extern int print_neigh(const struct sockaddr_nl *who,
-		       const struct nlmsghdr *n, void *arg);
+		       struct nlmsghdr *n, void *arg);
 extern int ipaddr_list(int argc, char **argv);
 extern int ipaddr_list_link(int argc, char **argv);
 extern int iproute_monitor(int argc, char **argv);
@@ -14,7 +14,7 @@
 extern void ipaddr_reset_filter(int);
 extern void ipneigh_reset_filter(void);
 extern int print_route(const struct sockaddr_nl *who, 
-		       const struct nlmsghdr *n, void *arg);
+		       struct nlmsghdr *n, void *arg);
 extern int do_ipaddr(int argc, char **argv);
 extern int do_iproute(int argc, char **argv);
 extern int do_iprule(int argc, char **argv);
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 24c9322..ae6f8c1 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -126,7 +126,8 @@
 		printf("qlen %d", ifr.ifr_qlen);
 }
 
-int print_linkinfo(const struct sockaddr_nl *who, const struct nlmsghdr *n, void *arg)
+int print_linkinfo(const struct sockaddr_nl *who, 
+		   struct nlmsghdr *n, void *arg)
 {
 	FILE *fp = (FILE*)arg;
 	struct ifinfomsg *ifi = NLMSG_DATA(n);
@@ -275,7 +276,7 @@
 	return 0;
 }
 
-int print_addrinfo(const struct sockaddr_nl *who, const struct nlmsghdr *n, 
+int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, 
 		   void *arg)
 {
 	FILE *fp = (FILE*)arg;
@@ -466,7 +467,7 @@
 }
 
 
-static int store_nlmsg(const struct sockaddr_nl *who, const struct nlmsghdr *n, 
+static int store_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, 
 		       void *arg)
 {
 	struct nlmsg_list **linfo = (struct nlmsg_list**)arg;
diff --git a/ip/ipmonitor.c b/ip/ipmonitor.c
index 46373e7..7f5041a 100644
--- a/ip/ipmonitor.c
+++ b/ip/ipmonitor.c
@@ -34,7 +34,7 @@
 
 
 int accept_msg(const struct sockaddr_nl *who,
-	       const struct nlmsghdr *n, void *arg)
+	       struct nlmsghdr *n, void *arg)
 {
 	FILE *fp = (FILE*)arg;
 
diff --git a/ip/ipneigh.c b/ip/ipneigh.c
index c3105ef..33e90ad 100644
--- a/ip/ipneigh.c
+++ b/ip/ipneigh.c
@@ -217,7 +217,7 @@
 }
 
 
-int print_neigh(const struct sockaddr_nl *who, const struct nlmsghdr *n, void *arg)
+int print_neigh(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 {
 	FILE *fp = (FILE*)arg;
 	struct ndmsg *r = NLMSG_DATA(n);
diff --git a/ip/iproute.c b/ip/iproute.c
index c91075c..ccea83b 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -103,7 +103,7 @@
 	return 0;
 }
 
-int print_route(const struct sockaddr_nl *who, const struct nlmsghdr *n, void *arg)
+int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 {
 	FILE *fp = (FILE*)arg;
 	struct rtmsg *r = NLMSG_DATA(n);
diff --git a/ip/iprule.c b/ip/iprule.c
index ced6785..8c1fc27 100644
--- a/ip/iprule.c
+++ b/ip/iprule.c
@@ -32,7 +32,7 @@
 
 static void usage(void)
 {
-	fprintf(stderr, "Usage: ip rule [ list | add | del ] SELECTOR ACTION\n");
+	fprintf(stderr, "Usage: ip rule [ list | add | del | flush ] SELECTOR ACTION\n");
 	fprintf(stderr, "SELECTOR := [ from PREFIX ] [ to PREFIX ] [ tos TOS ] [ fwmark FWMARK ]\n");
 	fprintf(stderr, "            [ dev STRING ] [ pref NUMBER ]\n");
 	fprintf(stderr, "ACTION := [ table TABLE_ID ] [ nat ADDRESS ]\n");
@@ -42,7 +42,7 @@
 	exit(-1);
 }
 
-static int print_rule(const struct sockaddr_nl *who, const struct nlmsghdr *n,
+static int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n,
 		      void *arg)
 {
 	FILE *fp = (FILE*)arg;
@@ -160,7 +160,7 @@
 	return 0;
 }
 
-int iprule_list(int argc, char **argv)
+static int iprule_list(int argc, char **argv)
 {
 	struct rtnl_handle rth;
 	int af = preferred_family;
@@ -190,7 +190,7 @@
 }
 
 
-int iprule_modify(int cmd, int argc, char **argv)
+static int iprule_modify(int cmd, int argc, char **argv)
 {
 	int table_ok = 0;
 	struct rtnl_handle rth;
@@ -303,6 +303,64 @@
 	return 0;
 }
 
+
+static int flush_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+{
+	struct rtnl_handle rth;
+	struct rtmsg *r = NLMSG_DATA(n);
+	int len = n->nlmsg_len;
+	struct rtattr * tb[RTA_MAX+1];
+
+	len -= NLMSG_LENGTH(sizeof(*r));
+	if (len < 0)
+		return -1;
+
+	memset(tb, 0, sizeof(tb));
+	parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
+
+	if (tb[RTA_PRIORITY]) {
+		n->nlmsg_type = RTM_DELRULE;
+		n->nlmsg_flags = NLM_F_REQUEST;
+
+		if (rtnl_open(&rth, 0) < 0)
+			return -1;
+
+		if (rtnl_talk(&rth, n, 0, 0, NULL, NULL, NULL) < 0)
+			return -2;
+	}
+
+	return 0;
+}
+
+static int iprule_flush(int argc, char **argv)
+{
+	struct rtnl_handle rth;
+	int af = preferred_family;
+
+	if (af == AF_UNSPEC)
+		af = AF_INET;
+
+	if (argc > 0) {
+		fprintf(stderr, "\"ip rule flush\" need not any arguments.\n");
+		return -1;
+	}
+
+	if (rtnl_open(&rth, 0) < 0)
+		return 1;
+
+	if (rtnl_wilddump_request(&rth, af, RTM_GETRULE) < 0) {
+		perror("Cannot send dump request");
+		return 1;
+	}
+
+	if (rtnl_dump_filter(&rth, flush_rule, NULL, NULL, NULL) < 0) {
+		fprintf(stderr, "Flush terminated\n");
+		return 1;
+	}
+
+	return 0;
+}
+
 int do_iprule(int argc, char **argv)
 {
 	if (argc < 1) {
@@ -315,6 +373,8 @@
 		return iprule_modify(RTM_NEWRULE, argc-1, argv+1);
 	} else if (matches(argv[0], "delete") == 0) {
 		return iprule_modify(RTM_DELRULE, argc-1, argv+1);
+	} else if (matches(argv[0], "flush") == 0) {
+		return iprule_flush(argc-1, argv+1);
 	} else if (matches(argv[0], "help") == 0)
 		usage();
 
diff --git a/ip/rtmon.c b/ip/rtmon.c
index 76ef8b9..5ce7731 100644
--- a/ip/rtmon.c
+++ b/ip/rtmon.c
@@ -46,7 +46,7 @@
 	fwrite((void*)n1, 1, NLMSG_ALIGN(n1->nlmsg_len), fp);
 }
 
-static int dump_msg(const struct sockaddr_nl *who, const struct nlmsghdr *n, 
+static int dump_msg(const struct sockaddr_nl *who, struct nlmsghdr *n, 
 		    void *arg)
 {
 	FILE *fp = (FILE*)arg;
diff --git a/ip/xfrm_policy.c b/ip/xfrm_policy.c
index fc17a64..95ee01d 100644
--- a/ip/xfrm_policy.c
+++ b/ip/xfrm_policy.c
@@ -336,7 +336,7 @@
 }
 
 static int xfrm_policy_print(const struct sockaddr_nl *who, 
-			     const struct nlmsghdr *n, void *arg)
+			     struct nlmsghdr *n, void *arg)
 {
 	FILE *fp = (FILE*)arg;
 	struct xfrm_userpolicy_info *xpinfo = NLMSG_DATA(n);
@@ -521,7 +521,7 @@
  * and store it to buffer.
  */
 static int xfrm_policy_keep(const struct sockaddr_nl *who,
-			    const struct nlmsghdr *n,
+			    struct nlmsghdr *n,
 			    void *arg)
 {
 	struct xfrm_buffer *xb = (struct xfrm_buffer *)arg;
diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c
index 54750f4..65f027f 100644
--- a/ip/xfrm_state.c
+++ b/ip/xfrm_state.c
@@ -375,7 +375,7 @@
 }
 
 static int xfrm_state_print(const struct sockaddr_nl *who,
-			    const struct nlmsghdr *n,
+			    struct nlmsghdr *n,
 			    void *arg)
 {
 	FILE *fp = (FILE*)arg;
@@ -517,7 +517,7 @@
  * and store it to buffer.
  */
 static int xfrm_state_keep(const struct sockaddr_nl *who,
-			   const struct nlmsghdr *n,
+			   struct nlmsghdr *n,
 			   void *arg)
 {
 	struct xfrm_buffer *xb = (struct xfrm_buffer *)arg;
diff --git a/lib/ll_map.c b/lib/ll_map.c
index e5798d3..89c0d20 100644
--- a/lib/ll_map.c
+++ b/lib/ll_map.c
@@ -35,7 +35,8 @@
 
 static struct idxmap *idxmap[16];
 
-int ll_remember_index(const struct sockaddr_nl *who, const struct nlmsghdr *n, void *arg)
+int ll_remember_index(const struct sockaddr_nl *who, 
+		      struct nlmsghdr *n, void *arg)
 {
 	int h;
 	struct ifinfomsg *ifi = NLMSG_DATA(n);
diff --git a/misc/ifstat.c b/misc/ifstat.c
index b6f1b87..19b1ff5 100644
--- a/misc/ifstat.c
+++ b/misc/ifstat.c
@@ -63,7 +63,7 @@
 struct ifstat_ent *kern_db;
 struct ifstat_ent *hist_db;
 
-int match(char *id)
+static int match(const char *id)
 {
 	int i;
 
@@ -77,7 +77,8 @@
 	return 0;
 }
 
-int get_nlmsg(const struct sockaddr_nl *who, const struct nlmsghdr *m, void *arg)
+static int get_nlmsg(const struct sockaddr_nl *who, 
+		     struct nlmsghdr *m, void *arg)
 {
 	struct ifinfomsg *ifi = NLMSG_DATA(m);
 	struct rtattr * tb[IFLA_MAX+1];
diff --git a/tc/m_action.c b/tc/m_action.c
index f6edc0d..dc30306 100644
--- a/tc/m_action.c
+++ b/tc/m_action.c
@@ -303,7 +303,7 @@
 }
 
 static int do_print_action(const struct sockaddr_nl *who,
-			   const struct nlmsghdr *n,
+			   struct nlmsghdr *n,
 			   void *arg)
 {
 	FILE *fp = (FILE*)arg;
diff --git a/tc/tc_class.c b/tc/tc_class.c
index 0352fd6..b4aae95 100644
--- a/tc/tc_class.c
+++ b/tc/tc_class.c
@@ -152,7 +152,7 @@
 __u32 filter_qdisc;
 
 static int print_class(const struct sockaddr_nl *who, 
-		       const struct nlmsghdr *n, void *arg)
+		       struct nlmsghdr *n, void *arg)
 {
 	FILE *fp = (FILE*)arg;
 	struct tcmsg *t = NLMSG_DATA(n);
diff --git a/tc/tc_filter.c b/tc/tc_filter.c
index 74e9969..af663dd 100644
--- a/tc/tc_filter.c
+++ b/tc/tc_filter.c
@@ -186,7 +186,7 @@
 static __u32 filter_protocol;
 
 static int print_filter(const struct sockaddr_nl *who,
-			const struct nlmsghdr *n, 
+			struct nlmsghdr *n, 
 			void *arg)
 {
 	FILE *fp = (FILE*)arg;
diff --git a/tc/tc_qdisc.c b/tc/tc_qdisc.c
index 6cf08d8..fe7e354 100644
--- a/tc/tc_qdisc.c
+++ b/tc/tc_qdisc.c
@@ -203,7 +203,7 @@
 static int filter_ifindex;
 
 static int print_qdisc(const struct sockaddr_nl *who, 
-		       const struct nlmsghdr *n, 
+		       struct nlmsghdr *n, 
 		       void *arg)
 {
 	FILE *fp = (FILE*)arg;