$NetBSD: patch-bz,v 1.1 2005/08/26 08:41:46 spz Exp $

--- src/RtConfig/f_junos.cc.orig	2003-07-24 13:20:48.000000000 +0200
+++ src/RtConfig/f_junos.cc
@@ -53,10 +53,9 @@
 
 #include "config.h"
 #include <cstring>
-#include <iostream.h>
-#include <strstream.h>
-#include <iomanip.h>
-#include <strstream.h>
+#include <iostream>
+#include <sstream>
+#include <iomanip>
 #include <cctype>
 #include "normalform/NE.hh"
 #include "irr/irr.hh"
@@ -66,6 +65,8 @@
 #include "f_junos.hh"
 #include "rpsl/schema.hh"
 
+using namespace std;
+
 #define DBG_JUNOS 7
 #define EXPORT 0
 #define IMPORT 1
@@ -85,12 +86,14 @@ bool JunosConfig::exportStatics = false;
 
 //////////////////////////// caches ////////////////////////////////
 
+// most of these are already defined in f_cisco.cc
 //AccessListManager<regexp_nf>         aspathMgr;
 //AccessListManager<SetOfPrefix>       prefixMgr(100);
-//AccessListManager<SetOfPrefix>       pktFilterMgr(100);
+//AccessListManager<SetOfIPv6Prefix>   ipv6prefixMgr(100);
 //AccessListManager<FilterOfCommunity> communityMgr;
+AccessListManager<CommunitySet>		 communityMgr2;
+//AccessListManager<SetOfPrefix>       pktFilterMgr(100);
 
-AccessListManager<CommunitySet> communityMgr2;
 
 void JunosConfig::printMartians() {
    static int done = 0;
@@ -101,21 +104,21 @@ void JunosConfig::printMartians() {
    done = 1;
 
    // print martians
-   char *martians = " 
-            route-filter 127.0.0.0/8 orlonger reject;
-            route-filter 10.0.0.0/8 orlonger reject;
-            route-filter 172.16.0.0/12 orlonger reject;
-            route-filter 192.168.0.0/16 orlonger reject;
-            route-filter 192.0.2.0/24 orlonger reject;
-            route-filter 128.0.0.0/16 orlonger reject;
-            route-filter 191.255.0.0/16 orlonger reject;
-            route-filter 192.0.0.0/24 orlonger reject;
-            route-filter 223.255.255.0/24 orlonger reject;
-            route-filter 224.0.0.0/3 orlonger reject;
-            route-filter 169.254.0.0/16 orlonger reject;
-            route-filter 0.0.0.0/0 upto /31 next policy;
-            route-filter 0.0.0.0/0 upto /32 reject;
-";
+   char *martians =
+            "route-filter 127.0.0.0/8 orlonger reject;\n"
+            "route-filter 10.0.0.0/8 orlonger reject;\n"
+            "route-filter 172.16.0.0/12 orlonger reject;\n"
+            "route-filter 192.168.0.0/16 orlonger reject;\n"
+            "route-filter 192.0.2.0/24 orlonger reject;\n"
+            "route-filter 128.0.0.0/16 orlonger reject;\n"
+            "route-filter 191.255.0.0/16 orlonger reject;\n"
+            "route-filter 192.0.0.0/24 orlonger reject;\n"
+            "route-filter 223.255.255.0/24 orlonger reject;\n"
+            "route-filter 224.0.0.0/3 orlonger reject;\n"
+            "route-filter 169.254.0.0/16 orlonger reject;\n"
+            "route-filter 0.0.0.0/0 upto /31 next policy;\n"
+            "route-filter 0.0.0.0/0 upto /32 reject;\n"
+   ;
    
    cout << "   policy-statement supress-martians {\n"
 	<< "      term martians {\n"
@@ -126,6 +129,93 @@ void JunosConfig::printMartians() {
 	<< "   }\n\n";
 }
 
+ListOf2Ints *JunosConfig::printRoutes(SetOfIPv6Prefix& nets) {
+
+	// return the access list number if something is printed
+	ListOf2Ints *result;
+
+	if (nets.universal())
+		return NULL;
+
+	// check to see if we already printed an identical access list
+	if (useAclCaches && (result = ipv6prefixMgr.search(nets)))
+		return result;
+
+	result = ipv6prefixMgr.add(nets);
+	int aclID = ipv6prefixMgr.newID();
+	result->add(aclID, aclID);
+
+	int allow_flag = 1;
+	if (nets.negated())
+		allow_flag = 0;
+
+   char *permitOrDeny = " reject;";
+   char *negatedPermitOrDeny = " accept;";
+   if (allow_flag) {
+      permitOrDeny = " accept;";
+      negatedPermitOrDeny = " reject;";
+   }
+   
+   cout << "   policy-statement prefix-list-" << aclID << " {\n"
+    << "      term prefixes {\n"
+    << "         from {\n";
+
+   IPv6RadixSet::SortedPrefixIterator itr(&nets.members);
+   ipv6_addr_t addr;
+   u_int leng;
+   char buffer[256];
+   /*
+   if (compressAcls) {
+      u_int start;
+      u_int end;
+      for (bool ok = itr.first(addr, leng, start, end);
+       ok;
+       ok = itr.next(addr, leng, start, end)) {
+     for (unsigned int sibling=0; sibling < (1<<(start-leng)); ++sibling)
+{
+        unsigned int siblingMask = sibling << (128 - start);
+        ipv6_addr_t siblingAddr = addr | siblingMask;
+   
+        cout << "            route-filter ";
+        cout << ipv62hex(&siblingAddr, buffer) << "/" << start;
+   
+        if (end != start)
+           cout << " upto /" << end;
+        else
+           cout << " exact";
+   
+        cout  << permitOrDeny << "\n";
+     }
+      }
+   } else {
+   */
+      for (bool ok = itr.first(addr, leng);
+       ok;
+       ok = itr.next(addr, leng)) {
+     cout << "            route-filter ";
+   
+     cout << ipv62hex(&addr, buffer) << "/" << leng;
+   
+     cout  << " exact" << permitOrDeny << "\n";
+      }
+/*   } */
+
+   cout << "         }\n"
+    << "      }\n"
+    << "      term catch-rest {\n";
+   
+   // terminate the acess lis
+   if (allow_flag)
+      cout << "          then reject;\n";
+   else
+      cout << "          then accept;\n";
+
+   cout << "      }\n"
+    << "   }\n\n";
+   
+   return result;
+}
+
 ListOf2Ints *JunosConfig::printRoutes(SetOfPrefix& nets) {
    // return the access list number if something is printed
    ListOf2Ints *result;
@@ -330,18 +420,17 @@ int JunosConfig::printRE_(ostream& os, c
 }
 
 int JunosConfig::printRE(ostream& os, const regexp& r) {
-   strstream sout;
+   ostringstream out;
    bool hasBOL = false;
    bool hasEOL = false;
-   printRE_(sout, r, hasBOL, hasEOL);
-   sout << ends;
+   printRE_(out, r, hasBOL, hasEOL);
+   out << ends;
    
    if (!hasBOL)
       os << ".* ";
-   os << sout.str();
+   os << out.str();
    if (!hasEOL)
       os << " .*";   
-   sout.freeze(0);
 
    return 1;
 }
@@ -465,8 +554,8 @@ int JunosConfig::printCommunitySet(ostre
 ListOf2Ints *JunosConfig::printCommunities(FilterOfCommunity& cm) {
    // return the access list numbers if something is printed
    ListOf2Ints *result;
-   ostrstream lastCout;
-   ostrstream midCout;
+   ostringstream lastCout;
+   ostringstream midCout;
    int term = 0;
    int id;
 
@@ -575,13 +664,11 @@ ListOf2Ints *JunosConfig::printCommuniti
 
       midCout << ends;
       cout << midCout.str();
-      midCout.freeze(0);
       
       cout << "   }\n\n";
    
       lastCout << ends;
       cout << "\n" << lastCout.str();
-      lastCout.freeze(0);
 
       for (int i = 1; i <= count; ++i)
 	 cout << "      term comm-" << aclID << "-" << ++term << " {\n"
@@ -592,11 +679,9 @@ ListOf2Ints *JunosConfig::printCommuniti
    } else {
       lastCout << ends;
       cout << "\n" << lastCout.str();
-      lastCout.freeze(0);
 
       midCout << ends;
       cout << midCout.str();
-      midCout.freeze(0);
    }      
 
    cout << "      term community-" << aclID << "-catch-rest {\n"
@@ -607,7 +692,7 @@ ListOf2Ints *JunosConfig::printCommuniti
    return result;
 }
 
-void JunosConfig::printActions(ostream &os, PolicyActionList *actions) {
+void JunosConfig::printActions(ostream &os, PolicyActionList *actions, ItemAFI *afi) {
 #define UNIMPLEMENTED_METHOD \
    cerr << "Warning: unimplemented method " \
 	<< actn->rp_attr->name << "." << actn->rp_method->name << endl
@@ -625,10 +710,19 @@ void JunosConfig::printActions(ostream &
 
       if (actn->rp_attr == dctn_rp_nhop) {
 	 if (actn->rp_method == dctn_rp_nhop_set) {
-	    char buffer[32];
-	    IPAddr *ip = ((ItemIPV4 *) actn->args->head())->ipv4;
-	    ip->get_text(buffer);
-	    os << "            nexthop " << buffer << ";\n";
+		if (afi->is_ipv4() && (typeid(*(actn->args->head())) == typeid(ItemIPV4))) {
+			char buffer[32];
+			IPAddr *ip = ((ItemIPV4 *) actn->args->head())->ipv4;
+			ip->get_text(buffer);
+			os << "            nexthop " << buffer << ";\n";
+		} else if (afi->is_ipv6() && (typeid(*(actn->args->head())) == typeid(ItemIPV6))) {
+			char buffer[50];
+			IPv6Addr *ip = ((ItemIPV6 *) actn->args->head())->ipv6;
+			ip->get_text(buffer);
+			os << " set ipv6 next-hop " << buffer << "\n";
+		} else {
+			cout << "Warning: next-hop address family doesn't match protocol address family, ignoring next-hop..." << endl;
+		}
 	 } else 
 	    UNIMPLEMENTED_METHOD;
 	 continue;
@@ -719,13 +813,14 @@ int JunosConfig::printDeclarations(Norma
       (void) printCommunities(nt->community);
       (void) printASPaths(nt->as_path);
       (void) printRoutes(nt->prfx_set);
+      (void) printRoutes(nt->ipv6_prfx_set);
    }
 
    return 1;
 }
 
 int JunosConfig::print(NormalExpression *ne, PolicyActionList *actn, 
-		       int import_flag) {
+		       int import_flag, ItemAFI *afi) {
    int last = 0;
    static ListOf2Ints empty_list(1);
 
@@ -745,7 +840,14 @@ int JunosConfig::print(NormalExpression 
    for (NormalTerm *nt = ne->first(); nt; nt = ne->next()) {
       ListOf2Ints *aspath_acls = printASPaths(nt->as_path);
       ListOf2Ints *comm_acls   = printCommunities(nt->community);
-      ListOf2Ints *prfx_acls   = printRoutes(nt->prfx_set);
+      ListOf2Ints *prfx_acls;
+
+	  if (afi->is_ipv4()) {
+		prfx_acls = printRoutes(nt->prfx_set);
+	  } else if (afi->is_ipv6()) {
+		prfx_acls = printRoutes(nt->ipv6_prfx_set);
+	  }
+
 
       if (!aspath_acls)
 	 aspath_acls = &empty_list;
@@ -779,7 +881,7 @@ int JunosConfig::print(NormalExpression 
 
 		  cout << "         }\n"
 		       << "         then {\n";
-		  JunosConfig::printActions(cout, actn);
+		  JunosConfig::printActions(cout, actn, afi);
 		  cout << "         }\n";
 		  cout << "      }\n\n";
 	       }
@@ -791,11 +893,18 @@ int JunosConfig::print(NormalExpression 
    return last;
 }
 
-bool JunosConfig::printNeighbor(int import, 
-				ASt peerAS, char *neighbor, bool peerGroup) {
+bool JunosConfig::printNeighbor(int import, ASt asno,
+				ASt peerAS, char *neighbor, bool peerGroup,
+				ItemAFI *peer_afi, ItemAFI *filter_afi) {
+   bool afi_activate = false;
+
    if (! printRouteMap)
       return false;
 
+   if (!peerGroup && (!filter_afi->is_default() || !peer_afi->is_default()))
+		afi_activate = true;
+
+   const char *indent = (afi_activate) ? " " : "";
    const char *direction = (import == IMPORT) ? "import" : "export";
 
    cout << "protocols {\n"
@@ -822,6 +931,12 @@ bool JunosConfig::printNeighbor(int impo
       setMEDtoIGP = false;
    }
 
+   if (afi_activate) {
+	  cout << "            family " << (AddressFamily &) *filter_afi << " { "<< endl;
+	  cout << "                any;" << endl;
+	  cout << "            } " << endl;
+   }
+
    cout << "         }\n"
 	<< "      }\n"
 	<< "   }\n"
@@ -830,11 +945,11 @@ bool JunosConfig::printNeighbor(int impo
    return true;
 }
 
-void JunosConfig::exportP(ASt asno, IPAddr *addr, 
-			  ASt peerAS, IPAddr *peer_addr) {
+void JunosConfig::exportP(ASt asno, MPPrefix *addr, 
+			  ASt peerAS, MPPrefix *peer_addr) {
 
    // Made asno part of the map name if it's not changed by users
-   sprintf(mapName, mapNameFormat, asno, mapCount++);
+   sprintf(mapName, mapNameFormat, peerAS, mapCount++);
 
    // get the aut-num object
    const AutNum *autnum = irr->getAutNum(asno);
@@ -847,32 +962,52 @@ void JunosConfig::exportP(ASt asno, IPAd
    // get matching export attributes
    AutNumSelector<AttrExport> itr(autnum, "export", 
 				  NULL, peerAS, peer_addr, addr);
-   const FilterAction *fa = itr.first();
+   AutNumSelector<AttrExport> itr1(autnum, "mp-export",
+				  NULL, peerAS, peer_addr, addr);
+
+   List<FilterAction> *common_list = itr.get_fa_list();
+   common_list->splice(*(itr1.get_fa_list()));
+
+   FilterAction *fa = common_list->head();
    if (! fa)	{
-	printPolicyWarning(asno, addr, peerAS, peer_addr, "export");
+   		printPolicyWarning(asno, addr, peerAS, peer_addr, "export/mp-export");
       	return;
    }
 
+   ItemList *afi_list = itr.get_afi_list();
+   afi_list->merge(*(itr1.get_afi_list()));
+
+   if (afi_list->isEmpty()) {
+		cout << "Warning: No AFI resulted from policy" << endl;
+   }
+
    cout << "policy-options {\n";
    printMartians();
 
    NormalExpression *ne;
-   int last = 0;
-   for (; fa && !last; fa = itr.next()) {
-      ne = NormalExpression::evaluate(fa->filter, peerAS);
-      last = printDeclarations(ne, fa->action, EXPORT);
-      delete ne;
+   NormalExpression done;
+   int last;
+
+   for (Item *afi = afi_list->head(); afi; afi = afi_list->next(afi)) {
+		last = 0;
+		for (fa = common_list->head(); fa && !last; fa = common_list->next(fa)) {
+
+			ne = NormalExpression::evaluate(new FilterAFI((ItemAFI *) afi->dup(), fa->filter), peerAS);
+			last = printDeclarations(ne, fa->action, EXPORT);
+			delete ne;
+		}
    }
 
    cout << "   policy-statement " << mapName << " {\n";
 
-   fa = itr.first();
-   last = 0;
-   for (; fa && !last; fa = itr.next()) {
-      ne = NormalExpression::evaluate(fa->filter, peerAS);
-      last = print(ne, fa->action, EXPORT);
-      delete ne;
-   }
+   for (Item *afi = afi_list->head(); afi; afi = afi_list->next(afi)) {
+		last = 0;
+		for (fa = common_list->head(); fa && !last; fa = common_list->next(fa)) {
+		  ne = NormalExpression::evaluate(new FilterAFI((ItemAFI *) afi->dup(), fa->filter), peerAS);
+		  last = print(ne, fa->action, EXPORT, (ItemAFI *) afi);
+		  delete ne;
+	   }
+	}
 
    cout << "      term " << mapName << "-catch-rest {\n"
 	<< "         then reject;\n"
@@ -880,14 +1015,16 @@ void JunosConfig::exportP(ASt asno, IPAd
 	<< "   }\n"
 	<< "}\n\n";
 
-   printNeighbor(EXPORT, peerAS, peer_addr->get_text(), false);
+   ItemAFI *peer_afi = new ItemAFI(peer_addr->get_afi());
+
+   printNeighbor(EXPORT, asno, peerAS, peer_addr->get_ip_text(), false, (ItemAFI *) peer_afi, (ItemAFI *) afi_list);
 }
 
-void JunosConfig::importP(ASt asno, IPAddr *addr, 
-			 ASt peerAS, IPAddr *peer_addr) {
+void JunosConfig::importP(ASt asno, MPPrefix *addr, 
+			 ASt peerAS, MPPrefix *peer_addr) {
 
    // Made asno part of the map name if it's not changed by users
-   sprintf(mapName, mapNameFormat, asno, mapCount++);
+   sprintf(mapName, mapNameFormat, peerAS, mapCount++);
 
    // get the aut-num object
    const AutNum *autnum = irr->getAutNum(asno);
@@ -901,31 +1038,47 @@ void JunosConfig::importP(ASt asno, IPAd
    // get matching import attributes
    AutNumSelector<AttrImport> itr(autnum, "import", 
 				  NULL, peerAS, peer_addr, addr);
-   const FilterAction *fa = itr.first();
-   if (! fa) {
-   	printPolicyWarning(asno, addr, peerAS, peer_addr, "import");
-	return;
+   AutNumSelector<AttrExport> itr1(autnum, "mp-import",
+				  NULL, peerAS, peer_addr, addr);
+
+   List<FilterAction> *common_list = itr.get_fa_list();
+   common_list->splice(*(itr1.get_fa_list()));
+
+   FilterAction *fa = common_list->head();
+   if (! fa)	{
+   		printPolicyWarning(asno, addr, peerAS, peer_addr, "import/mp-import");
+      	return;
    }
 
+   ItemList *afi_list = itr.get_afi_list();
+   afi_list->merge(*(itr1.get_afi_list()));
+
    cout << "policy-options {\n";
    printMartians();
 
    NormalExpression *ne;
-   int last = 0;
-   for (; fa && !last; fa = itr.next()) {
-      ne = NormalExpression::evaluate(fa->filter, peerAS);
-      last = printDeclarations(ne, fa->action, IMPORT);
-      delete ne;
+   NormalExpression done;
+   int last;
+
+   for (Item *afi = afi_list->head(); afi; afi = afi_list->next(afi)) {
+		last = 0;
+		for (fa = common_list->head(); fa && !last; fa = common_list->next(fa)) {
+
+			ne = NormalExpression::evaluate(new FilterAFI((ItemAFI *) afi->dup(), fa->filter), peerAS);
+			last = printDeclarations(ne, fa->action, IMPORT);
+			delete ne;
+		}
    }
 
    cout << "   policy-statement " << mapName << " {\n";
 
-   fa = itr.first();
-   last = 0;
-   for (; fa && !last; fa = itr.next()) {
-      ne = NormalExpression::evaluate(fa->filter, peerAS);
-      last = print(ne, fa->action, IMPORT);
-      delete ne;
+   for (Item *afi = afi_list->head(); afi; afi = afi_list->next(afi)) {
+		last = 0;
+   		for (fa = common_list->head(); fa && !last; fa = common_list->next(fa)) {
+			ne = NormalExpression::evaluate(new FilterAFI((ItemAFI *) afi->dup(), fa->filter), peerAS);
+			last = print(ne, fa->action, IMPORT, (ItemAFI *) afi);
+			delete ne;
+		}
    }
 
    cout << "      term " << mapName << "-catch-rest {\n"
@@ -934,11 +1087,14 @@ void JunosConfig::importP(ASt asno, IPAd
 	<< "   }\n"
 	<< "}\n\n";
 
-   printNeighbor(IMPORT, peerAS, peer_addr->get_text(), false);
+   ItemAFI *peer_afi = new ItemAFI(peer_addr->get_afi());
+
+   printNeighbor(IMPORT, asno, peerAS, peer_addr->get_text(), false, (ItemAFI *) peer_afi, (ItemAFI *) afi_list);
 }
 
-void JunosConfig::static2bgp(ASt asno, IPAddr *addr) {
-   // Made asno part of the map name if it's not changed by users
+void JunosConfig::static2bgp(ASt asno, MPPrefix *addr) {
+
+   // make static2bgp map obvious
    strcpy(mapName, "static2bgp");
 
    // get the aut-num object
@@ -952,30 +1108,45 @@ void JunosConfig::static2bgp(ASt asno, I
    // get matching import attributes
    AutNumSelector<AttrImport> itr(autnum, "import", 
 				  NULL, asno, addr, addr, "STATIC");
-   const FilterAction *fa = itr.first();
+   AutNumSelector<AttrImport> itr1(autnum, "mp-import", 
+				  NULL, asno, addr, addr, "STATIC");
+
+   List<FilterAction> *common_list = itr.get_fa_list();
+   common_list->splice(*(itr1.get_fa_list()));
+
+   const FilterAction *fa = common_list->head();
    if (! fa)
       cerr << "Warning: AS" << asno 
 	   << " has no static2bgp policy for AS" << asno << endl;
 
+   ItemList *afi_list = itr.get_afi_list();
+   afi_list->merge(*(itr1.get_afi_list()));
+
    cout << "policy-options {\n";
    printMartians();
 
    NormalExpression *ne;
-   int last = 0;
-   for (; fa && !last; fa = itr.next()) {
-      ne = NormalExpression::evaluate(fa->filter, asno);
-      last = printDeclarations(ne, fa->action, STATIC);
-      delete ne;
+   NormalExpression done;
+   int last;
+
+   for (Item *afi = afi_list->head(); afi; afi = afi_list->next(afi)) {
+		last = 0;
+		for (fa = common_list->head(); fa && !last; fa = common_list->next(fa)) {
+		  ne = NormalExpression::evaluate(new FilterAFI((ItemAFI *) afi->dup(), fa->filter), asno);
+		  last = printDeclarations(ne, fa->action, STATIC);
+		  delete ne;
+		}
    }
 
    cout << "   policy-statement static2bgp {\n";
 
-   fa = itr.first();
-   last = 0;
-   for (; fa && !last; fa = itr.next()) {
-      ne = NormalExpression::evaluate(fa->filter, asno);
-      last = print(ne, fa->action, STATIC);
-      delete ne;
+   for (Item *afi = afi_list->head(); afi; afi = afi_list->next(afi)) {
+		last = 0;
+		for (fa = common_list->head(); fa && !last; fa = common_list->next(fa)) {
+			ne = NormalExpression::evaluate(new FilterAFI((ItemAFI *) afi->dup(), fa->filter), asno);
+			last = print(ne, fa->action, STATIC, (ItemAFI *) afi);
+			delete ne;
+		}
    }
 
    cout << "      term static2bgp-catch-rest {\n"
@@ -1004,7 +1175,23 @@ void JunosConfig::networks(ASt asno) {
    }
 }
 
+void JunosConfig::IPv6networks(ASt asno) {
+   static char buffer[128];
+   static char buffer2[128];
+   const MPPrefixRanges *nets = irr->expandAS(asno);
+   MPPrefixRanges::const_iterator p;
+
+   for (p = nets->begin(); p != nets->end(); ++p) {
+     if (p->ipv6) {
+       cout << "network " << p->ipv6->get_ip_text()
+            << " mask " << p->ipv6->get_mask()
+            << ";\n";
+     }
+   }
+}
+
 void JunosConfig::exportGroup(ASt asno, char * pset) {
+
    // Made asno part of the map name if it's not changed by users
    sprintf(mapName, mapNameFormat, asno, mapCount++);
 
@@ -1019,30 +1206,43 @@ void JunosConfig::exportGroup(ASt asno, 
    SymID psetID = symbols.symID(pset);
    // get matching export attributes
    AutNumSelector<AttrExport> itr(autnum, "export", psetID, ~0, NULL, NULL);
-   const FilterAction *fa = itr.first();
+   AutNumSelector<AttrExport> itr1(autnum, "mp-export", psetID, ~0, NULL, NULL);
+   
+   List<FilterAction> *common_list = itr.get_fa_list();
+   common_list->splice(*(itr1.get_fa_list()));
+
+   FilterAction *fa = common_list->head();
    if (! fa)
       cerr << "Warning: AS" << asno 
-	   << " has no export policy for " << pset << endl;
+	   << " has no export/mp-export policy for " << pset << endl;
+
+   ItemList *afi_list = itr.get_afi_list();
+   afi_list->merge(*(itr1.get_afi_list()));
 
    cout << "policy-options {\n";
    printMartians();
 
    NormalExpression *ne;
-   int last = 0;
-   for (; fa && !last; fa = itr.next()) {
-      ne = NormalExpression::evaluate(fa->filter, ~0);
-      last = printDeclarations(ne, fa->action, EXPORT);
-      delete ne;
+   int last;
+
+   for (Item *afi = afi_list->head(); afi; afi = afi_list->next(afi)) {
+		last = 0;
+	   for (fa = common_list->head(); fa && !last; fa = common_list->next(fa)) {
+		  ne = NormalExpression::evaluate(new FilterAFI((ItemAFI *) afi->dup(), fa->filter), ~0);
+		  last = printDeclarations(ne, fa->action, EXPORT);
+		  delete ne;
+	   }
    }
 
    cout << "   policy-statement " << mapName << " {\n";
 
-   fa = itr.first();
-   last = 0;
-   for (; fa && !last; fa = itr.next()) {
-      ne = NormalExpression::evaluate(fa->filter, ~0);
-      last = print(ne, fa->action, EXPORT);
-      delete ne;
+   for (Item *afi = afi_list->head(); afi; afi = afi_list->next(afi)) {
+		last = 0;
+	   for (fa = common_list->head(); fa && !last; fa = common_list->next(fa)) {
+		  ne = NormalExpression::evaluate(new FilterAFI((ItemAFI *) afi->dup(), fa->filter), ~0);
+		  last = print(ne, fa->action, EXPORT, (ItemAFI *) afi);
+		  delete ne;
+	   }
    }
 
    cout << "      term " << mapName << "-catch-rest {\n"
@@ -1117,30 +1317,44 @@ void JunosConfig::importGroup(ASt asno, 
    SymID psetID = symbols.symID(pset);
    // get matching import attributes
    AutNumSelector<AttrImport> itr(autnum, "import", psetID, ~0, NULL, NULL);
-   const FilterAction *fa = itr.first();
+   AutNumSelector<AttrExport> itr1(autnum, "mp-import", psetID, ~0, NULL, NULL);
+   
+   List<FilterAction> *common_list = itr.get_fa_list();
+   common_list->splice(*(itr1.get_fa_list()));
+
+   FilterAction *fa = common_list->head();
+
    if (! fa)
       cerr << "Warning: AS" << asno 
-	   << " has no import policy for " << pset << endl;
+	   << " has no import/mp-import policy for " << pset << endl;
+
+   ItemList *afi_list = itr.get_afi_list();
+   afi_list->merge(*(itr1.get_afi_list()));
 
    cout << "policy-options {\n";
    printMartians();
 
    NormalExpression *ne;
-   int last = 0;
-   for (; fa && !last; fa = itr.next()) {
-      ne = NormalExpression::evaluate(fa->filter, ~0);
-      last = printDeclarations(ne, fa->action, IMPORT);
-      delete ne;
+   int last;
+
+   for (Item *afi = afi_list->head(); afi; afi = afi_list->next(afi)) {
+		last = 0;
+	   for (fa = common_list->head(); fa && !last; fa = common_list->next(fa)) {
+		  ne = NormalExpression::evaluate(new FilterAFI((ItemAFI *) afi->dup(), fa->filter), ~0);
+		  last = printDeclarations(ne, fa->action, IMPORT);
+		  delete ne;
+	   }
    }
 
    cout << "   policy-statement " << mapName << " {\n";
 
-   fa = itr.first();
-   last = 0;
-   for (; fa && !last; fa = itr.next()) {
-      ne = NormalExpression::evaluate(fa->filter, ~0);
-      last = print(ne, fa->action, IMPORT);
-      delete ne;
+   for (Item *afi = afi_list->head(); afi; afi = afi_list->next(afi)) {
+		last = 0;
+	   for (fa = common_list->head(); fa && !last; fa = common_list->next(fa)) {
+		  ne = NormalExpression::evaluate(new FilterAFI((ItemAFI *) afi->dup(), fa->filter), ~0);
+		  last = print(ne, fa->action, IMPORT, (ItemAFI *) afi);
+		  delete ne;
+	   }
    }
 
    cout << "      term " << mapName << "-catch-rest {\n"
