Merge remote branch 'origin/master'
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index 13f32b8..440815b 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -1122,6 +1122,42 @@
   return 1;
 }
 
+/* AS path confed check.  If aspath contains confed set or sequence then return 1. */
+int
+aspath_confed_check (struct aspath *aspath)
+{
+  struct assegment *seg;
+
+  if ( !(aspath && aspath->segments) )
+    return 0;
+
+  seg = aspath->segments;
+
+  while (seg)
+    {
+      if (seg->type == AS_CONFED_SET || seg->type == AS_CONFED_SEQUENCE)
+	  return 1;
+      seg = seg->next;
+    }
+  return 0;
+}
+
+/* Leftmost AS path segment confed check.  If leftmost AS segment is of type
+  AS_CONFED_SEQUENCE or AS_CONFED_SET then return 1.  */
+int
+aspath_left_confed_check (struct aspath *aspath)
+{
+
+  if ( !(aspath && aspath->segments) )
+    return 0;
+
+  if ( (aspath->segments->type == AS_CONFED_SEQUENCE)
+      || (aspath->segments->type == AS_CONFED_SET) )
+    return 1;
+
+  return 0;
+}
+
 /* Merge as1 to as2.  as2 should be uninterned aspath. */
 static struct aspath *
 aspath_merge (struct aspath *as1, struct aspath *as2)
@@ -1172,6 +1208,10 @@
   while (seg1 && seg1->next)
     seg1 = seg1->next;
 
+  /* Delete any AS_CONFED_SEQUENCE segment from as2. */
+  if (seg1->type == AS_SEQUENCE && seg2->type == AS_CONFED_SEQUENCE)
+    as2 = aspath_delete_confed_seq (as2);
+
   /* Compare last segment type of as1 and first segment type of as2. */
   if (seg1->type != seg2->type)
     return aspath_merge (as1, as2);
diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h
index 2b4625c..9854d18 100644
--- a/bgpd/bgp_aspath.h
+++ b/bgpd/bgp_aspath.h
@@ -88,6 +88,8 @@
 extern int aspath_loop_check (struct aspath *, as_t);
 extern int aspath_private_as_check (struct aspath *);
 extern int aspath_firstas_check (struct aspath *, as_t);
+extern int aspath_confed_check (struct aspath *);
+extern int aspath_left_confed_check (struct aspath *);
 extern unsigned long aspath_count (void);
 extern unsigned int aspath_count_hops (struct aspath *);
 extern unsigned int aspath_count_confeds (struct aspath *);
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 9416837..a664858 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -872,6 +872,17 @@
 
   bgp = peer->bgp;
     
+  /* Confederation sanity check. */
+  if ((peer_sort (peer) == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) ||
+     (peer_sort (peer) == BGP_PEER_EBGP && aspath_confed_check (attr->aspath)))
+    {
+      zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host);
+      bgp_notify_send (peer, 
+		       BGP_NOTIFY_UPDATE_ERR, 
+		       BGP_NOTIFY_UPDATE_MAL_AS_PATH);
+      return -1;
+    }
+
   /* First AS check for EBGP. */
   if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
     {
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index 7784700..ade0fbc 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -39,6 +39,13 @@
 
 extern struct zebra_privs_t bgpd_privs;
 
+/* BGP listening socket. */
+struct bgp_listener
+{
+  int fd;
+  union sockunion su;
+  struct thread *thread;
+};
 
 /*
  * Set MD5 key for the socket, for the given IPv4 peer address.
@@ -365,37 +372,90 @@
   bgp_nexthop_set (peer->su_local, peer->su_remote, &peer->nexthop, peer);
 }
 
+
+static int
+bgp_listener (int sock, struct sockaddr *sa, socklen_t salen)
+{
+  struct bgp_listener *listener;
+  int ret, en;
+
+  sockopt_reuseaddr (sock);
+  sockopt_reuseport (sock);
+
+#ifdef IPTOS_PREC_INTERNETCONTROL
+  if (sa->sa_family == AF_INET)
+    setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL);
+#endif
+
+#ifdef IPV6_V6ONLY
+  /* Want only IPV6 on ipv6 socket (not mapped addresses) */
+  if (sa->sa_family == AF_INET6) {
+    int on = 1;
+    setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY,
+		(void *) &on, sizeof (on));
+  }
+#endif
+
+  if (bgpd_privs.change (ZPRIVS_RAISE) )
+    zlog_err ("bgp_socket: could not raise privs");
+
+  ret = bind (sock, sa, salen);
+  en = errno;
+  if (bgpd_privs.change (ZPRIVS_LOWER) )
+    zlog_err ("bgp_bind_address: could not lower privs");
+
+  if (ret < 0)
+    {
+      zlog_err ("bind: %s", safe_strerror (en));
+      return ret;
+    }
+
+  ret = listen (sock, 3);
+  if (ret < 0)
+    {
+      zlog_err ("listen: %s", safe_strerror (errno));
+      return ret;
+    }
+
+  listener = XMALLOC (MTYPE_BGP_LISTENER, sizeof(*listener));
+  listener->fd = sock;
+  memcpy(&listener->su, sa, salen);
+  listener->thread = thread_add_read (master, bgp_accept, listener, sock);
+  listnode_add (bm->listen_sockets, listener);
+
+  return 0;
+}
+
 /* IPv6 supported version of BGP server socket setup.  */
 #if defined (HAVE_IPV6) && ! defined (NRL)
 int
-bgp_socket (struct bgp *bgp, unsigned short port, char *address)
+bgp_socket (unsigned short port, const char *address)
 {
-  int ret, en;
-  struct addrinfo req;
   struct addrinfo *ainfo;
   struct addrinfo *ainfo_save;
-  int sock = 0;
+  static const struct addrinfo req = {
+    .ai_family = AF_UNSPEC,
+    .ai_flags = AI_PASSIVE,
+    .ai_socktype = SOCK_STREAM,
+  };
+  int ret, count;
   char port_str[BUFSIZ];
 
-  memset (&req, 0, sizeof (struct addrinfo));
-
-  req.ai_flags = AI_PASSIVE;
-  req.ai_family = AF_UNSPEC;
-  req.ai_socktype = SOCK_STREAM;
   snprintf (port_str, sizeof(port_str), "%d", port);
   port_str[sizeof (port_str) - 1] = '\0';
 
-  ret = getaddrinfo (address, port_str, &req, &ainfo);
+  ret = getaddrinfo (address, port_str, &req, &ainfo_save);
   if (ret != 0)
     {
       zlog_err ("getaddrinfo: %s", gai_strerror (ret));
       return -1;
     }
 
-  ainfo_save = ainfo;
-
-  do
+  count = 0;
+  for (ainfo = ainfo_save; ainfo; ainfo = ainfo->ai_next)
     {
+      int sock;
+
       if (ainfo->ai_family != AF_INET && ainfo->ai_family != AF_INET6)
 	continue;
      
@@ -406,59 +466,25 @@
 	  continue;
 	}
 
-      sockopt_reuseaddr (sock);
-      sockopt_reuseport (sock);
-      
-#ifdef IPTOS_PREC_INTERNETCONTROL
-      if (ainfo->ai_family == AF_INET)
-	setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL);
-#endif
-
-#ifdef IPV6_V6ONLY
-      /* Want only IPV6 on ipv6 socket (not mapped addresses) */
-      if (ainfo->ai_family == AF_INET6) {
-	int on = 1;
-	setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, 
-		    (void *) &on, sizeof (on));
-      }
-#endif
-
-      if (bgpd_privs.change (ZPRIVS_RAISE) )
-        zlog_err ("bgp_socket: could not raise privs");
-
-      ret = bind (sock, ainfo->ai_addr, ainfo->ai_addrlen);
-      en = errno;
-      if (bgpd_privs.change (ZPRIVS_LOWER) )
-	zlog_err ("bgp_bind_address: could not lower privs");
-
-      if (ret < 0)
-	{
-	  zlog_err ("bind: %s", safe_strerror (en));
-	  close(sock);
-	  continue;
-	}
-      
-      ret = listen (sock, 3);
-      if (ret < 0) 
-	{
-	  zlog_err ("listen: %s", safe_strerror (errno));
-	  close (sock);
-	  continue;
-	}
-      
-      listnode_add (bm->listen_sockets, (void *)(long)sock);
-      thread_add_read (master, bgp_accept, bgp, sock);
+      ret = bgp_listener (sock, ainfo->ai_addr, ainfo->ai_addrlen);
+      if (ret == 0)
+	++count;
+      else
+	close(sock);
     }
-  while ((ainfo = ainfo->ai_next) != NULL);
-
   freeaddrinfo (ainfo_save);
+  if (count == 0)
+    {
+      zlog_err ("%s: no usable addresses", __func__);
+      return -1;
+    }
 
-  return sock;
+  return 0;
 }
 #else
 /* Traditional IPv4 only version.  */
 int
-bgp_socket (struct bgp *bgp, unsigned short port, char *address)
+bgp_socket (unsigned short port, const char *address)
 {
   int sock;
   int socklen;
@@ -472,15 +498,7 @@
       return sock;
     }
 
-  sockopt_reuseaddr (sock);
-  sockopt_reuseport (sock);
-
-#ifdef IPTOS_PREC_INTERNETCONTROL
-  setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL);
-#endif
-
   memset (&sin, 0, sizeof (struct sockaddr_in));
-
   sin.sin_family = AF_INET;
   sin.sin_port = htons (port);
   socklen = sizeof (struct sockaddr_in);
@@ -495,33 +513,27 @@
   sin.sin_len = socklen;
 #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
 
-  if ( bgpd_privs.change (ZPRIVS_RAISE) )
-    zlog_err ("bgp_socket: could not raise privs");
-
-  ret = bind (sock, (struct sockaddr *) &sin, socklen);
-  en = errno;
-
-  if (bgpd_privs.change (ZPRIVS_LOWER) )
-    zlog_err ("bgp_socket: could not lower privs");
-
-  if (ret < 0)
-    {
-      zlog_err ("bind: %s", safe_strerror (en));
-      close (sock);
-      return ret;
-    }
-  
-  ret = listen (sock, 3);
+  ret = bgp_listener (sock, (struct sockaddr *) &sin, socklen);
   if (ret < 0) 
     {
-      zlog_err ("listen: %s", safe_strerror (errno));
       close (sock);
       return ret;
     }
-
-  listnode_add (bm->listen_sockets, (void *)(long)sock);
-  thread_add_read (bm->master, bgp_accept, bgp, sock);
-
   return sock;
 }
 #endif /* HAVE_IPV6 && !NRL */
+
+void
+bgp_close (void)
+{
+  struct listnode *node, *next;
+  struct bgp_listener *listener;
+
+  for (ALL_LIST_ELEMENTS (bm->listen_sockets, node, next, listener))
+    {
+      thread_cancel (listener->thread);
+      close (listener->fd);
+      listnode_delete (bm->listen_sockets, listener);
+      XFREE (MTYPE_BGP_LISTENER, listener);
+    }
+}
diff --git a/bgpd/bgp_network.h b/bgpd/bgp_network.h
index 618d8db..5bf2e5f 100644
--- a/bgpd/bgp_network.h
+++ b/bgpd/bgp_network.h
@@ -21,7 +21,8 @@
 #ifndef _QUAGGA_BGP_NETWORK_H
 #define _QUAGGA_BGP_NETWORK_H
 
-extern int bgp_socket (struct bgp *, unsigned short, char *);
+extern int bgp_socket (unsigned short, const char *);
+extern void bgp_close (void);
 extern int bgp_connect (struct peer *);
 extern void bgp_getsockname (struct peer *);
 
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 13c37b5..88be52e 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -2820,10 +2820,11 @@
   return CMD_SUCCESS;
 }
 
-#define BGP_UPDATE_SOURCE_STR "(A.B.C.D|X:X::X:X)"
+#define BGP_UPDATE_SOURCE_STR "(A.B.C.D|X:X::X:X|WORD)"
 #define BGP_UPDATE_SOURCE_HELP_STR \
   "IPv4 address\n" \
-  "IPv6 address\n"
+  "IPv6 address\n" \
+  "Interface name (requires zebra to be running)\n"
 
 DEFUN (neighbor_update_source,
        neighbor_update_source_cmd,
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 60722d2..ef8fbe9 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -2036,6 +2036,13 @@
 	}
     }
 
+  /* Create BGP server socket, if first instance.  */
+  if (list_isempty(bm->bgp))
+    {
+      if (bgp_socket (bm->port, bm->address) < 0)
+	return BGP_ERR_INVALID_VALUE;
+    }
+
   bgp = bgp_create (as, name);
   listnode_add (bm->bgp, bgp);
   bgp_router_id_set(bgp, &router_id_zebra);
@@ -2081,7 +2088,9 @@
    * routes to be processed still referencing the struct bgp.
    */
   listnode_delete (bm->bgp, bgp);
-  
+  if (list_isempty(bm->bgp))
+    bgp_close ();
+
   bgp_unlock(bgp);  /* initial reference */
   
   return 0;
@@ -2262,7 +2271,7 @@
   u_char peer_down;
 };
 
-struct peer_flag_action peer_flag_action_list[] = 
+static const struct peer_flag_action peer_flag_action_list[] =
   {
     { PEER_FLAG_PASSIVE,                  0, peer_change_reset },
     { PEER_FLAG_SHUTDOWN,                 0, peer_change_reset },
@@ -2274,7 +2283,7 @@
     { 0, 0, 0 }
   };
 
-struct peer_flag_action peer_af_flag_action_list[] = 
+static const struct peer_flag_action peer_af_flag_action_list[] =
   {
     { PEER_FLAG_NEXTHOP_SELF,             1, peer_change_reset_out },
     { PEER_FLAG_SEND_COMMUNITY,           1, peer_change_reset_out },
@@ -2295,14 +2304,14 @@
 
 /* Proper action set. */
 static int
-peer_flag_action_set (struct peer_flag_action *action_list, int size,
+peer_flag_action_set (const struct peer_flag_action *action_list, int size,
 		      struct peer_flag_action *action, u_int32_t flag)
 {
   int i;
   int found = 0;
   int reset_in = 0;
   int reset_out = 0;
-  struct peer_flag_action *match = NULL;
+  const struct peer_flag_action *match = NULL;
 
   /* Check peer's frag action.  */
   for (i = 0; i < size; i++)
@@ -5137,9 +5146,6 @@
   /* BGP VTY commands installation.  */
   bgp_vty_init ();
 
-  /* Create BGP server socket.  */
-  bgp_socket (NULL, bm->port, bm->address);
-
   /* Init zebra. */
   bgp_zebra_init ();
 
diff --git a/lib/memtypes.c b/lib/memtypes.c
index dd365dd..05d9322 100644
--- a/lib/memtypes.c
+++ b/lib/memtypes.c
@@ -91,6 +91,7 @@
 struct memory_list memory_list_bgp[] =
 {
   { MTYPE_BGP,			"BGP instance"			},
+  { MTYPE_BGP_LISTENER,		"BGP listen socket details"	},
   { MTYPE_BGP_PEER,		"BGP peer"			},
   { MTYPE_BGP_PEER_HOST,	"BGP peer hostname"		},
   { MTYPE_PEER_GROUP,		"Peer group"			},
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index 7083c96..0a8ac3e 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -134,8 +134,9 @@
   ifp = zebra_interface_state_read (zclient->ibuf);
   if (IS_OSPF6_DEBUG_ZEBRA (RECV))
     zlog_debug ("Zebra Interface state change: "
-                "%s index %d flags %ld metric %d mtu %d",
-		ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu6);
+                "%s index %d flags %llx metric %d mtu %d",
+		ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, 
+		ifp->metric, ifp->mtu6);
 
   ospf6_interface_state_update (ifp);
   return 0;
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index 150ffac..8f624a4 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -91,8 +91,9 @@
   ifp = zebra_interface_add_read (zclient->ibuf);
 
   if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
-    zlog_debug ("Zebra: interface add %s index %d flags %ld metric %d mtu %d",
-               ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
+    zlog_debug ("Zebra: interface add %s index %d flags %llx metric %d mtu %d",
+               ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
+               ifp->metric, ifp->mtu);
 
   assert (ifp->info);
 
@@ -132,7 +133,7 @@
 
   if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
     zlog_debug
-      ("Zebra: interface delete %s index %d flags %ld metric %d mtu %d",
+      ("Zebra: interface delete %s index %d flags %lld metric %d mtu %d",
        ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
 
 #ifdef HAVE_SNMP
diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c
index 827663a..4f80bf4 100644
--- a/ripd/rip_interface.c
+++ b/ripd/rip_interface.c
@@ -402,8 +402,9 @@
   rip_if_down(ifp);
  
   if (IS_RIP_DEBUG_ZEBRA)
-    zlog_debug ("interface %s index %d flags %ld metric %d mtu %d is down",
-	       ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
+    zlog_debug ("interface %s index %d flags %llx metric %d mtu %d is down",
+	       ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
+	       ifp->metric, ifp->mtu);
 
   return 0;
 }
@@ -422,7 +423,7 @@
     return 0;
 
   if (IS_RIP_DEBUG_ZEBRA)
-    zlog_debug ("interface %s index %d flags %ld metric %d mtu %d is up",
+    zlog_debug ("interface %s index %d flags %lld metric %d mtu %d is up",
 	       ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
 
   /* Check if this interface is RIP enabled or not.*/
@@ -446,7 +447,7 @@
   ifp = zebra_interface_add_read (zclient->ibuf);
 
   if (IS_RIP_DEBUG_ZEBRA)
-    zlog_debug ("interface add %s index %d flags %ld metric %d mtu %d",
+    zlog_debug ("interface add %s index %d flags %lld metric %d mtu %d",
 	       ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
 
   /* Check if this interface is RIP enabled or not.*/
@@ -485,7 +486,7 @@
     rip_if_down(ifp);
   } 
   
-  zlog_info("interface delete %s index %d flags %ld metric %d mtu %d",
+  zlog_info("interface delete %s index %d flags %lld metric %d mtu %d",
 	    ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);  
   
   /* To support pseudo interface do not free interface structure.  */
diff --git a/ripd/ripd.c b/ripd/ripd.c
index c865ace..2d5a856 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -1372,6 +1372,9 @@
 #ifdef RIP_RECVMSG
   setsockopt_pktinfo (sock);
 #endif /* RIP_RECVMSG */
+#ifdef IPTOS_PREC_INTERNETCONTROL
+  setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL);
+#endif
 
   if (ripd_privs.change (ZPRIVS_RAISE))
       zlog_err ("rip_create_socket: could not raise privs");
diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c
index d70c299..c23d32a 100644
--- a/ripngd/ripng_interface.c
+++ b/ripngd/ripng_interface.c
@@ -243,8 +243,9 @@
     return 0;
 
   if (IS_RIPNG_DEBUG_ZEBRA)
-    zlog_debug ("interface up %s index %d flags %ld metric %d mtu %d",
-	       ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu6);
+    zlog_debug ("interface up %s index %d flags %llx metric %d mtu %d",
+	       ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
+	       ifp->metric, ifp->mtu6);
 
   /* Check if this interface is RIPng enabled or not. */
   ripng_enable_apply (ifp);
@@ -276,7 +277,7 @@
   ripng_if_down (ifp);
 
   if (IS_RIPNG_DEBUG_ZEBRA)
-    zlog_debug ("interface down %s index %d flags %ld metric %d mtu %d",
+    zlog_debug ("interface down %s index %d flags %lld metric %d mtu %d",
 	       ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu6);
 
   return 0;
@@ -291,7 +292,7 @@
   ifp = zebra_interface_add_read (zclient->ibuf);
 
   if (IS_RIPNG_DEBUG_ZEBRA)
-    zlog_debug ("RIPng interface add %s index %d flags %ld metric %d mtu %d",
+    zlog_debug ("RIPng interface add %s index %d flags %lld metric %d mtu %d",
 	       ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu6);
 
   /* Check is this interface is RIP enabled or not.*/
@@ -324,7 +325,7 @@
     ripng_if_down(ifp);
   }
 
-  zlog_info("interface delete %s index %d flags %ld metric %d mtu %d",
+  zlog_info("interface delete %s index %d flags %lld metric %d mtu %d",
             ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu6);
 
   /* To support pseudo interface do not free interface structure.  */