Merge bgpd changeset 1184 from Zebra repository by Rivo Nurges.
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index 2f9cc94..4adbcf5 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -158,6 +158,15 @@
   return new;
 }
 
+/* Retrun string representation of communities attribute. */
+char *
+ecommunity_str (struct ecommunity *ecom)
+{
+  if (! ecom->str)
+    ecom->str = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_DISPLAY);
+  return ecom->str;
+}
+
 /* Merge two Extended Communities Attribute structure.  */
 struct ecommunity *
 ecommunity_merge (struct ecommunity *ecom1, struct ecommunity *ecom2)
@@ -559,24 +568,30 @@
 
   for (i = 0; i < ecom->size; i++)
     {
+      /* Space between each value.  */
+      if (! first)
+	str_buf[str_pnt++] = ' ';
+
       pnt = ecom->val + (i * 8);
 
       /* High-order octet of type. */
       encode = *pnt++;
       if (encode != ECOMMUNITY_ENCODE_AS && encode != ECOMMUNITY_ENCODE_IP)
 	{
-	  if (str_buf)
-	    XFREE (MTYPE_ECOMMUNITY_STR, str_buf);
-	  return "Unknown";
+	  len = sprintf (str_buf + str_pnt, "?");
+	  str_pnt += len;
+	  first = 0;
+	  continue;
 	}
       
       /* Low-order octet of type. */
       type = *pnt++;
       if (type !=  ECOMMUNITY_ROUTE_TARGET && type != ECOMMUNITY_SITE_ORIGIN)
 	{
-	  if (str_buf)
-	    XFREE (MTYPE_ECOMMUNITY_STR, str_buf);
-	  return "Unknown";
+	  len = sprintf (str_buf + str_pnt, "?");
+	  str_pnt += len;
+	  first = 0;
+	  continue;
 	}
 
       switch (format)
@@ -591,9 +606,7 @@
 	  prefix = "";
 	  break;
 	default:
-	  if (str_buf)
-	    XFREE (MTYPE_ECOMMUNITY_STR, str_buf);
-	  return "Unknown";
+	  prefix = "";
 	  break;
 	}
 
@@ -604,10 +617,6 @@
 	  str_buf = XREALLOC (MTYPE_ECOMMUNITY_STR, str_buf, str_size);
 	}
 
-      /* Space between each value.  */
-      if (! first)
-	str_buf[str_pnt++] = ' ';
-
       /* Put string into buffer.  */
       if (encode == ECOMMUNITY_ENCODE_AS)
 	{
@@ -639,3 +648,33 @@
     }
   return str_buf;
 }
+
+int
+ecommunity_match (struct ecommunity *ecom1, struct ecommunity *ecom2)
+{
+  int i = 0;
+  int j = 0;
+
+  if (ecom1 == NULL && ecom2 == NULL)
+    return 1;
+
+  if (ecom1 == NULL || ecom2 == NULL)
+    return 0;
+
+  if (ecom1->size < ecom2->size)
+    return 0;
+
+  /* Every community on com2 needs to be on com1 for this to match */
+  while (i < ecom1->size && j < ecom2->size)
+    {
+      if (memcmp (ecom1->val + i, ecom2->val + j, ECOMMUNITY_SIZE) == 0)
+        j++;
+      i++;
+    }
+
+  if (j == ecom2->size)
+    return 1;
+  else
+    return 0;
+}
+