Minor fixes from Masahide for XFRM dynamic keying
diff --git a/ip/xfrm.h b/ip/xfrm.h
index 60d597e..2f33c06 100644
--- a/ip/xfrm.h
+++ b/ip/xfrm.h
@@ -39,6 +39,12 @@
 #define XFRMP_RTA(x)  ((struct rtattr*)(((char*)(x)) + NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_info))))
 #define XFRMP_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct xfrm_userpoilcy_info))
 
+#define XFRMSID_RTA(x)  ((struct rtattr*)(((char*)(x)) + NLMSG_ALIGN(sizeof(struct xfrm_usersa_id))))
+#define XFRMSID_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct xfrm_usersa_id))
+
+#define XFRMPID_RTA(x)  ((struct rtattr*)(((char*)(x)) + NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id))))
+#define XFRMPID_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct xfrm_userpoilcy_id))
+
 #define XFRMACQ_RTA(x)	((struct rtattr*)(((char*)(x)) + NLMSG_ALIGN(sizeof(struct xfrm_user_acquire))))
 #define XFRMEXP_RTA(x)	((struct rtattr*)(((char*)(x)) + NLMSG_ALIGN(sizeof(struct xfrm_user_expire))))
 #define XFRMPEXP_RTA(x)	((struct rtattr*)(((char*)(x)) + NLMSG_ALIGN(sizeof(struct xfrm_user_polexpire))))
diff --git a/ip/xfrm_monitor.c b/ip/xfrm_monitor.c
index f590428..153621f 100644
--- a/ip/xfrm_monitor.c
+++ b/ip/xfrm_monitor.c
@@ -103,6 +103,7 @@
 
 	if (oneline)
 		fprintf(fp, "\n");
+	fflush(fp);
 
 	return 0;
 }
@@ -116,14 +117,16 @@
 		print_timestamp(fp);
 
 	if (n->nlmsg_type == XFRM_MSG_NEWSA ||
-	     n->nlmsg_type == XFRM_MSG_DELSA ||
-	     n->nlmsg_type == XFRM_MSG_UPDSA) {
+	    n->nlmsg_type == XFRM_MSG_DELSA ||
+	    n->nlmsg_type == XFRM_MSG_UPDSA ||
+	    n->nlmsg_type == XFRM_MSG_EXPIRE) {
 		xfrm_state_print(who, n, arg);
 		return 0;
 	}
 	if (n->nlmsg_type == XFRM_MSG_NEWPOLICY ||
-	     n->nlmsg_type == XFRM_MSG_DELPOLICY ||
-	     n->nlmsg_type == XFRM_MSG_UPDPOLICY) {
+	    n->nlmsg_type == XFRM_MSG_DELPOLICY ||
+	    n->nlmsg_type == XFRM_MSG_UPDPOLICY ||
+	    n->nlmsg_type == XFRM_MSG_POLEXPIRE) {
 		xfrm_policy_print(who, n, arg);
 		return 0;
 	}
@@ -132,14 +135,6 @@
 		xfrm_acquire_print(who, n, arg);
 		return 0;
 	}
-	if (n->nlmsg_type == XFRM_MSG_EXPIRE) {
-		xfrm_state_print(who, n, arg);
-		return 0;
-	}
-	if (n->nlmsg_type == XFRM_MSG_POLEXPIRE) {
-		xfrm_policy_print(who, n, arg);
-		return 0;
-	}
 	if (n->nlmsg_type == XFRM_MSG_FLUSHSA) {
 		/* XXX: Todo: show proto in xfrm_usersa_flush */
 		fprintf(fp, "Flushed state\n");
diff --git a/ip/xfrm_policy.c b/ip/xfrm_policy.c
index e295eb9..433b513 100644
--- a/ip/xfrm_policy.c
+++ b/ip/xfrm_policy.c
@@ -345,24 +345,23 @@
 
 	if (n->nlmsg_type != XFRM_MSG_NEWPOLICY &&
 	    n->nlmsg_type != XFRM_MSG_DELPOLICY &&
+	    n->nlmsg_type != XFRM_MSG_UPDPOLICY &&
 	    n->nlmsg_type != XFRM_MSG_POLEXPIRE) {
 		fprintf(stderr, "Not a policy: %08x %08x %08x\n",
 			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
 		return 0;
 	}
 
-	if (n->nlmsg_type == XFRM_MSG_POLEXPIRE) {
-		xpexp = NLMSG_DATA(n);
-		xpinfo = &xpexp->pol;
-
-		len -= NLMSG_LENGTH(sizeof(*xpexp));
-	} else if (n->nlmsg_type == XFRM_MSG_DELPOLICY)  {
+	if (n->nlmsg_type == XFRM_MSG_DELPOLICY)  {
 		xpid = NLMSG_DATA(n);
 		len -= NLMSG_LENGTH(sizeof(*xpid));
+	} else if (n->nlmsg_type == XFRM_MSG_POLEXPIRE) {
+		xpexp = NLMSG_DATA(n);
+		xpinfo = &xpexp->pol;
+		len -= NLMSG_LENGTH(sizeof(*xpexp));
 	} else {
 		xpexp = NULL;
 		xpinfo = NLMSG_DATA(n);
-
 		len -= NLMSG_LENGTH(sizeof(*xpinfo));
 	}
 
@@ -371,31 +370,37 @@
 		return -1;
 	}
 
-	if (!xfrm_policy_filter_match(xpinfo))
+	if (xpinfo && !xfrm_policy_filter_match(xpinfo))
 		return 0;
 
-	if (n->nlmsg_type == XFRM_MSG_POLEXPIRE)
+	if (n->nlmsg_type == XFRM_MSG_DELPOLICY)
+		fprintf(fp, "Deleted ");
+	else if (n->nlmsg_type == XFRM_MSG_UPDPOLICY)
+		fprintf(fp, "Updated ");
+	else if (n->nlmsg_type == XFRM_MSG_POLEXPIRE)
+		fprintf(fp, "Expired ");
+
+	if (n->nlmsg_type == XFRM_MSG_DELPOLICY)
+		rta = XFRMPID_RTA(xpid);
+	else if (n->nlmsg_type == XFRM_MSG_POLEXPIRE)
 		rta = XFRMPEXP_RTA(xpexp);
-	else if (n->nlmsg_type == XFRM_MSG_DELPOLICY) 
-		rta = (struct rtattr*)(((char*)(xpid)) + NLMSG_ALIGN(sizeof(*xpid)));
 	else
 		rta = XFRMP_RTA(xpinfo);
 
 	parse_rtattr(tb, XFRMA_MAX, rta, len);
 
 	if (n->nlmsg_type == XFRM_MSG_DELPOLICY) {
-		fprintf(fp, "Deleted ");
 		//xfrm_policy_id_print();
-		
-		if (tb[XFRMA_POLICY])
-		xpinfo = (struct xfrm_userpolicy_info *)RTA_DATA(tb[XFRMA_POLICY]);
-		else {
-			fprintf(stderr, "Buggy XFRM_MSG_DELPOLICY ");
-			return 0;
+		if (!tb[XFRMA_POLICY]) {
+			fprintf(stderr, "Buggy XFRM_MSG_DELPOLICY: no XFRMA_POLICY\n");
+			return -1;
 		}
-
-	} else if (n->nlmsg_type == XFRM_MSG_POLEXPIRE)
-		fprintf(fp, "Expired ");
+		if (RTA_PAYLOAD(tb[XFRMA_POLICY]) < sizeof(*xpinfo)) {
+			fprintf(stderr, "Buggy XFRM_MSG_DELPOLICY: too short XFRMA_POLICY len\n");
+			return -1;
+		}
+		xpinfo = (struct xfrm_userpolicy_info *)RTA_DATA(tb[XFRMA_POLICY]);
+	}
 
 	xfrm_policy_info_print(xpinfo, tb, fp, NULL, NULL);
 
@@ -407,6 +412,7 @@
 
 	if (oneline)
 		fprintf(fp, "\n");
+	fflush(fp);
 
 	return 0;
 }
diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c
index db7de0c..3eefaff 100644
--- a/ip/xfrm_state.c
+++ b/ip/xfrm_state.c
@@ -565,25 +565,24 @@
 
 	if (n->nlmsg_type != XFRM_MSG_NEWSA &&
 	    n->nlmsg_type != XFRM_MSG_DELSA &&
+	    n->nlmsg_type != XFRM_MSG_UPDSA &&
 	    n->nlmsg_type != XFRM_MSG_EXPIRE) {
 		fprintf(stderr, "Not a state: %08x %08x %08x\n",
 			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
 		return 0;
 	}
 
-	if (n->nlmsg_type == XFRM_MSG_EXPIRE) {
-		xexp = NLMSG_DATA(n);
-		xsinfo = &xexp->state;
-
-		len -= NLMSG_LENGTH(sizeof(*xexp));
-	} else if (n->nlmsg_type == XFRM_MSG_DELSA) {
+	if (n->nlmsg_type == XFRM_MSG_DELSA) {
 		/* Dont blame me for this .. Herbert made me do it */
 		xsid = NLMSG_DATA(n);
-		len -= NLMSG_LENGTH(sizeof(struct xfrm_usersa_id));
+		len -= NLMSG_LENGTH(sizeof(*xsid));
+	} else if (n->nlmsg_type == XFRM_MSG_EXPIRE) {
+		xexp = NLMSG_DATA(n);
+		xsinfo = &xexp->state;
+		len -= NLMSG_LENGTH(sizeof(*xexp));
 	} else {
 		xexp = NULL;
 		xsinfo = NLMSG_DATA(n);
-
 		len -= NLMSG_LENGTH(sizeof(*xsinfo));
 	}
 
@@ -592,33 +591,37 @@
 		return -1;
 	}
 
-	if (!xfrm_state_filter_match(xsinfo))
+	if (xsinfo && !xfrm_state_filter_match(xsinfo))
 		return 0;
 
-	if (n->nlmsg_type == XFRM_MSG_DELSA) {
+	if (n->nlmsg_type == XFRM_MSG_DELSA)
 		fprintf(fp, "Deleted ");
-		//xfrm_state_print_id();
-	}
+	else if (n->nlmsg_type == XFRM_MSG_UPDSA)
+		fprintf(fp, "Updated ");
 	else if (n->nlmsg_type == XFRM_MSG_EXPIRE)
 		fprintf(fp, "Expired ");
 
-	if (n->nlmsg_type == XFRM_MSG_EXPIRE)
+	if (n->nlmsg_type == XFRM_MSG_DELSA)
+		rta = XFRMSID_RTA(xsid);
+	else if (n->nlmsg_type == XFRM_MSG_EXPIRE)
 		rta = XFRMEXP_RTA(xexp);
-	else if (n->nlmsg_type == XFRM_MSG_DELSA)
-		rta = (struct rtattr*)(((char*)(xsid)) + NLMSG_ALIGN(sizeof(*xsid)));
 	else 
 		rta = XFRMS_RTA(xsinfo);
 
-
 	parse_rtattr(tb, XFRMA_MAX, rta, len);
 
 	if (n->nlmsg_type == XFRM_MSG_DELSA) {
-		if (tb[XFRMA_SA])
-			xsinfo = (struct xfrm_usersa_info *)RTA_DATA(tb[XFRMA_SA]);
-		else {
-			fprintf(stderr, "Buggy XFRM_MSG_DELSA ");
-			return 0;
+		//xfrm_policy_id_print();
+
+		if (!tb[XFRMA_SA]) {
+			fprintf(stderr, "Buggy XFRM_MSG_DELSA: no XFRMA_SA\n");
+			return -1;
 		}
+		if (RTA_PAYLOAD(tb[XFRMA_SA]) < sizeof(*xsinfo)) {
+			fprintf(stderr, "Buggy XFRM_MSG_DELPOLICY: too short XFRMA_POLICY len\n");
+			return -1;
+		}
+		xsinfo = (struct xfrm_usersa_info *)RTA_DATA(tb[XFRMA_SA]);
 	}
 
 	xfrm_state_info_print(xsinfo, tb, fp, NULL, NULL);
@@ -631,6 +634,7 @@
 
 	if (oneline)
 		fprintf(fp, "\n");
+	fflush(fp);
 
 	return 0;
 }