Initial revision
diff --git a/bgpd/.cvsignore b/bgpd/.cvsignore
new file mode 100644
index 0000000..8edffb6
--- /dev/null
+++ b/bgpd/.cvsignore
@@ -0,0 +1,8 @@
+Makefile
+*.o
+bgpd
+bgp_btoa
+bgpd.conf
+tags
+TAGS
+.deps
diff --git a/bgpd/BGP4-MIB.txt b/bgpd/BGP4-MIB.txt
new file mode 100644
index 0000000..c911316
--- /dev/null
+++ b/bgpd/BGP4-MIB.txt
@@ -0,0 +1,929 @@
+    BGP4-MIB DEFINITIONS ::= BEGIN
+
+        IMPORTS
+            MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE,
+            IpAddress, Integer32, Counter32, Gauge32, mib-2
+                FROM SNMPv2-SMI
+            MODULE-COMPLIANCE, OBJECT-GROUP, NOTIFICATION-GROUP
+                FROM SNMPv2-CONF;
+
+        bgp MODULE-IDENTITY
+            LAST-UPDATED "9902100000Z"
+            ORGANIZATION "IETF IDR Working Group"
+            CONTACT-INFO "E-mail:  idr@merit.net
+
+                          Susan Hares  (Editor)
+                          Merit Network
+                          4251 Plymouth Road
+                          Suite C
+                          Ann Arbor, MI 48105-2785
+                          Tel: +1 734 936 2095
+                          Fax: +1 734 647 3185
+                          E-mail: skh@merit.edu
+
+                          Jeff Johnson (Editor)
+                          RedBack Networks, Inc.
+                          1389 Moffett Park Drive
+                          Sunnyvale, CA  94089-1134
+                          Tel: +1 408 548 3516
+                          Fax: +1 408 548 3599
+                          E-mail: jeff@redback.com"
+            DESCRIPTION
+                    "The MIB module for BGP-4."
+            REVISION    "9902100000Z"
+            DESCRIPTION
+                    "Corrected duplicate OBJECT IDENTIFIER
+                     assignment in the conformance information."
+            REVISION    "9601080000Z"
+            DESCRIPTION
+                    "1) Fixed the definitions of the traps to
+                     make them equivalent to their initial
+                     definition in RFC 1269.
+                     2) Added compliance and conformance info."
+            ::= { mib-2 15 }
+
+        bgpVersion OBJECT-TYPE
+            SYNTAX     OCTET STRING (SIZE (1..255))
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "Vector of supported BGP protocol version
+                    numbers.  Each peer negotiates the version
+                    from this vector.  Versions are identified
+                    via the string of bits contained within this
+                    object.  The first octet contains bits 0 to
+                    7, the second octet contains bits 8 to 15,
+                    and so on, with the most significant bit
+                    referring to the lowest bit number in the
+                    octet (e.g., the MSB of the first octet
+                    refers to bit 0).  If a bit, i, is present
+                    and set, then the version (i+1) of the BGP
+                    is supported."
+            ::= { bgp 1 }
+
+        bgpLocalAs OBJECT-TYPE
+            SYNTAX     INTEGER (0..65535)
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The local autonomous system number."
+            ::= { bgp 2 }
+
+
+
+        -- BGP Peer table.  This table contains, one entry per BGP
+        -- peer, information about the BGP peer.
+
+        bgpPeerTable OBJECT-TYPE
+            SYNTAX     SEQUENCE OF BgpPeerEntry
+            MAX-ACCESS not-accessible
+            STATUS     current
+            DESCRIPTION
+                    "BGP peer table.  This table contains,
+                    one entry per BGP peer, information about the
+                    connections with BGP peers."
+            ::= { bgp 3 }
+
+        bgpPeerEntry OBJECT-TYPE
+            SYNTAX     BgpPeerEntry
+            MAX-ACCESS not-accessible
+            STATUS     current
+            DESCRIPTION
+                    "Entry containing information about the
+                    connection with a BGP peer."
+            INDEX { bgpPeerRemoteAddr }
+            ::= { bgpPeerTable 1 }
+
+        BgpPeerEntry ::= SEQUENCE {
+                bgpPeerIdentifier
+                    IpAddress,
+                bgpPeerState
+                    INTEGER,
+                bgpPeerAdminStatus
+                    INTEGER,
+                bgpPeerNegotiatedVersion
+                    Integer32,
+                bgpPeerLocalAddr
+                    IpAddress,
+                bgpPeerLocalPort
+                    INTEGER,
+                bgpPeerRemoteAddr
+                    IpAddress,
+                bgpPeerRemotePort
+                    INTEGER,
+                bgpPeerRemoteAs
+                    INTEGER,
+                bgpPeerInUpdates
+                    Counter32,
+                bgpPeerOutUpdates
+                    Counter32,
+                bgpPeerInTotalMessages
+                    Counter32,
+                bgpPeerOutTotalMessages
+                    Counter32,
+                bgpPeerLastError
+                    OCTET STRING,
+                bgpPeerFsmEstablishedTransitions
+                    Counter32,
+                bgpPeerFsmEstablishedTime
+                    Gauge32,
+                bgpPeerConnectRetryInterval
+                    INTEGER,
+                bgpPeerHoldTime
+                    INTEGER,
+                bgpPeerKeepAlive
+                    INTEGER,
+                bgpPeerHoldTimeConfigured
+                    INTEGER,
+                bgpPeerKeepAliveConfigured
+                    INTEGER,
+                bgpPeerMinASOriginationInterval
+                    INTEGER,
+                bgpPeerMinRouteAdvertisementInterval
+                    INTEGER,
+                bgpPeerInUpdateElapsedTime
+                    Gauge32
+                }
+
+        bgpPeerIdentifier OBJECT-TYPE
+            SYNTAX     IpAddress
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The BGP Identifier of this entry's BGP peer."
+            ::= { bgpPeerEntry 1 }
+
+        bgpPeerState OBJECT-TYPE
+            SYNTAX     INTEGER {
+                                idle(1),
+                                connect(2),
+                                active(3),
+                                opensent(4),
+                                openconfirm(5),
+                                established(6)
+                       }
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The BGP peer connection state."
+            ::= { bgpPeerEntry 2 }
+
+        bgpPeerAdminStatus OBJECT-TYPE
+            SYNTAX     INTEGER {
+                                stop(1),
+                                start(2)
+                       }
+            MAX-ACCESS read-write
+            STATUS     current
+            DESCRIPTION
+                    "The desired state of the BGP connection.  A
+                    transition from 'stop' to 'start' will cause
+                    the BGP Start Event to be generated.  A
+                    transition from 'start' to 'stop' will cause
+                    the BGP Stop Event to be generated.  This
+                    parameter can be used to restart BGP peer
+                    connections.  Care should be used in providing
+                    write access to this object without adequate
+                    authentication."
+            ::= { bgpPeerEntry 3 }
+
+        bgpPeerNegotiatedVersion OBJECT-TYPE
+            SYNTAX     Integer32
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The negotiated version of BGP running between
+                    the two peers."
+            ::= { bgpPeerEntry 4 }
+
+        bgpPeerLocalAddr OBJECT-TYPE
+            SYNTAX     IpAddress
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The local IP address of this entry's BGP
+                    connection."
+            ::= { bgpPeerEntry 5 }
+
+        bgpPeerLocalPort OBJECT-TYPE
+            SYNTAX     INTEGER (0..65535)
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The local port for the TCP connection between
+                    the BGP peers."
+            ::= { bgpPeerEntry 6 }
+
+        bgpPeerRemoteAddr OBJECT-TYPE
+            SYNTAX     IpAddress
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The remote IP address of this entry's BGP
+                    peer."
+            ::= { bgpPeerEntry 7 }
+
+        bgpPeerRemotePort OBJECT-TYPE
+            SYNTAX     INTEGER (0..65535)
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The remote port for the TCP connection between
+                    the BGP peers.  Note that the objects
+                    bgpPeerLocalAddr, bgpPeerLocalPort,
+                    bgpPeerRemoteAddr and bgpPeerRemotePort
+                    provide the appropriate reference to the
+                    standard MIB TCP connection table."
+            ::= { bgpPeerEntry 8 }
+
+        bgpPeerRemoteAs OBJECT-TYPE
+            SYNTAX     INTEGER (0..65535)
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The remote autonomous system number."
+            ::= { bgpPeerEntry 9 }
+
+        bgpPeerInUpdates OBJECT-TYPE
+            SYNTAX     Counter32
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The number of BGP UPDATE messages received on
+                    this connection.  This object should be
+                    initialized to zero (0) when the connection is
+                    established."
+            ::= { bgpPeerEntry 10 }
+
+        bgpPeerOutUpdates OBJECT-TYPE
+            SYNTAX     Counter32
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The number of BGP UPDATE messages transmitted
+                    on this connection.  This object should be
+                    initialized to zero (0) when the connection is
+                    established."
+            ::= { bgpPeerEntry 11 }
+
+        bgpPeerInTotalMessages OBJECT-TYPE
+            SYNTAX     Counter32
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The total number of messages received from the
+                    remote peer on this connection.  This object
+                    should be initialized to zero when the
+                    connection is established."
+            ::= { bgpPeerEntry 12 }
+
+        bgpPeerOutTotalMessages OBJECT-TYPE
+            SYNTAX     Counter32
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The total number of messages transmitted to
+                    the remote peer on this connection.  This object
+                    should be initialized to zero when the
+                    connection is established."
+            ::= { bgpPeerEntry 13 }
+
+        bgpPeerLastError OBJECT-TYPE
+            SYNTAX     OCTET STRING (SIZE (2))
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The last error code and subcode seen by this
+                    peer on this connection.  If no error has
+                    occurred, this field is zero.  Otherwise, the
+                    first byte of this two byte OCTET STRING
+                    contains the error code, and the second byte
+                    contains the subcode."
+            ::= { bgpPeerEntry 14 }
+
+        bgpPeerFsmEstablishedTransitions OBJECT-TYPE
+            SYNTAX     Counter32
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The total number of times the BGP FSM
+                    transitioned into the established state."
+            ::= { bgpPeerEntry 15 }
+
+        bgpPeerFsmEstablishedTime OBJECT-TYPE
+            SYNTAX     Gauge32
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "This timer indicates how long (in seconds) this
+                    peer has been in the Established state or how long
+                    since this peer was last in the Established state.
+                    It is set to zero when a new peer is configured or
+                    the router is booted."
+            ::= { bgpPeerEntry 16 }
+
+        bgpPeerConnectRetryInterval OBJECT-TYPE
+            SYNTAX     INTEGER (1..65535)
+            MAX-ACCESS read-write
+            STATUS     current
+            DESCRIPTION
+                    "Time interval in seconds for the ConnectRetry
+                    timer.  The suggested value for this timer is
+                    120 seconds."
+            ::= { bgpPeerEntry 17 }
+
+        bgpPeerHoldTime OBJECT-TYPE
+            SYNTAX     INTEGER  ( 0 | 3..65535 )
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "Time interval in seconds for the Hold Timer
+                    established with the peer.  The value of this
+                    object is calculated by this BGP speaker by
+                    using the smaller of the value in
+                    bgpPeerHoldTimeConfigured and the Hold Time
+                    received in the OPEN message.  This value
+                    must be at lease three seconds if it is not
+                    zero (0) in which case the Hold Timer has
+                    not been established with the peer, or, the
+                    value of bgpPeerHoldTimeConfigured is zero (0)."
+            ::= { bgpPeerEntry 18 }
+
+        bgpPeerKeepAlive OBJECT-TYPE
+            SYNTAX     INTEGER ( 0 | 1..21845 )
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "Time interval in seconds for the KeepAlive
+                    timer established with the peer.  The value of
+                    this object is calculated by this BGP speaker
+                    such that, when compared with bgpPeerHoldTime,
+                    it has the same proportion as what
+                    bgpPeerKeepAliveConfigured has when compared
+                    with bgpPeerHoldTimeConfigured.  If the value
+                    of this object is zero (0), it indicates that
+                    the KeepAlive timer has not been established
+                    with the peer, or, the value of
+                    bgpPeerKeepAliveConfigured is zero (0)."
+            ::= { bgpPeerEntry 19 }
+
+        bgpPeerHoldTimeConfigured OBJECT-TYPE
+            SYNTAX     INTEGER ( 0 | 3..65535 )
+            MAX-ACCESS read-write
+            STATUS     current
+            DESCRIPTION
+                    "Time interval in seconds for the Hold Time
+                    configured for this BGP speaker with this peer.
+                    This value is placed in an OPEN message sent to
+                    this peer by this BGP speaker, and is compared
+                    with the Hold Time field in an OPEN message
+                    received from the peer when determining the Hold
+                    Time (bgpPeerHoldTime) with the peer.  This value
+                    must not be less than three seconds if it is not
+                    zero (0) in which case the Hold Time is NOT to be
+                    established with the peer.  The suggested value for
+                    this timer is 90 seconds."
+            ::= { bgpPeerEntry 20 }
+
+        bgpPeerKeepAliveConfigured OBJECT-TYPE
+            SYNTAX     INTEGER ( 0 | 1..21845 )
+            MAX-ACCESS read-write
+            STATUS     current
+            DESCRIPTION
+                    "Time interval in seconds for the KeepAlive timer
+                    configured for this BGP speaker with this peer.
+                    The value of this object will only determine the
+                    KEEPALIVE messages' frequency relative to the value
+                    specified in bgpPeerHoldTimeConfigured; the actual
+                    time interval for the KEEPALIVE messages is
+                    indicated by bgpPeerKeepAlive.  A reasonable
+                    maximum value for this timer would be configured to
+                    be one third of that of bgpPeerHoldTimeConfigured.
+                    If the value of this object is zero (0), no
+                    periodical KEEPALIVE messages are sent to the peer
+                    after the BGP connection has been established.  The
+                    suggested value for this timer is 30 seconds."
+            ::= { bgpPeerEntry 21 }
+
+        bgpPeerMinASOriginationInterval OBJECT-TYPE
+            SYNTAX     INTEGER (1..65535)
+            MAX-ACCESS read-write
+            STATUS     current
+            DESCRIPTION
+                    "Time interval in seconds for the
+                    MinASOriginationInterval timer.
+                    The suggested value for this timer is 15 seconds."
+            ::= { bgpPeerEntry 22 }
+
+        bgpPeerMinRouteAdvertisementInterval OBJECT-TYPE
+            SYNTAX     INTEGER (1..65535)
+            MAX-ACCESS read-write
+            STATUS     current
+            DESCRIPTION
+                    "Time interval in seconds for the
+                    MinRouteAdvertisementInterval timer.
+                    The suggested value for this timer is 30 seconds."
+            ::= { bgpPeerEntry 23 }
+
+        bgpPeerInUpdateElapsedTime OBJECT-TYPE
+            SYNTAX     Gauge32
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "Elapsed time in seconds since the last BGP
+                    UPDATE message was received from the peer.
+                    Each time bgpPeerInUpdates is incremented,
+                    the value of this object is set to zero (0)."
+            ::= { bgpPeerEntry 24 }
+
+
+
+        bgpIdentifier OBJECT-TYPE
+            SYNTAX     IpAddress
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The BGP Identifier of local system."
+            ::= { bgp 4 }
+
+
+
+        -- Received Path Attribute Table.  This table contains,
+        -- one entry per path to a network, path attributes
+        -- received from all peers running BGP version 3 or less.
+        -- This table is obsolete, having been replaced in
+        -- functionality with the bgp4PathAttrTable.
+
+        bgpRcvdPathAttrTable OBJECT-TYPE
+            SYNTAX     SEQUENCE OF BgpPathAttrEntry
+            MAX-ACCESS not-accessible
+            STATUS     obsolete
+            DESCRIPTION
+                    "The BGP Received Path Attribute Table contains
+                    information about paths to destination networks
+                    received from all peers running BGP version 3 or
+                    less."
+            ::= { bgp 5 }
+
+        bgpPathAttrEntry OBJECT-TYPE
+            SYNTAX     BgpPathAttrEntry
+            MAX-ACCESS not-accessible
+            STATUS     obsolete
+            DESCRIPTION
+                    "Information about a path to a network."
+            INDEX { bgpPathAttrDestNetwork,
+                    bgpPathAttrPeer        }
+            ::= { bgpRcvdPathAttrTable 1 }
+
+        BgpPathAttrEntry ::= SEQUENCE {
+            bgpPathAttrPeer
+                 IpAddress,
+            bgpPathAttrDestNetwork
+                 IpAddress,
+            bgpPathAttrOrigin
+                 INTEGER,
+            bgpPathAttrASPath
+                 OCTET STRING,
+            bgpPathAttrNextHop
+                 IpAddress,
+            bgpPathAttrInterASMetric
+                 Integer32
+        }
+
+        bgpPathAttrPeer OBJECT-TYPE
+            SYNTAX     IpAddress
+            MAX-ACCESS read-only
+            STATUS     obsolete
+            DESCRIPTION
+                    "The IP address of the peer where the path
+                    information was learned."
+            ::= { bgpPathAttrEntry 1 }
+
+        bgpPathAttrDestNetwork OBJECT-TYPE
+            SYNTAX     IpAddress
+            MAX-ACCESS read-only
+            STATUS     obsolete
+            DESCRIPTION
+                    "The address of the destination network."
+            ::= { bgpPathAttrEntry 2 }
+
+        bgpPathAttrOrigin OBJECT-TYPE
+            SYNTAX     INTEGER {
+                           igp(1),-- networks are interior
+                           egp(2),-- networks learned via EGP
+                           incomplete(3) -- undetermined
+                       }
+            MAX-ACCESS read-only
+            STATUS     obsolete
+            DESCRIPTION
+                 "The ultimate origin of the path information."
+            ::= { bgpPathAttrEntry 3 }
+
+        bgpPathAttrASPath OBJECT-TYPE
+            SYNTAX     OCTET STRING (SIZE (2..255))
+            MAX-ACCESS read-only
+            STATUS     obsolete
+            DESCRIPTION
+                    "The set of ASs that must be traversed to reach
+                    the network.  This object is probably best
+                    represented as SEQUENCE OF INTEGER.  For SMI
+                    compatibility, though, it is represented as
+                    OCTET STRING.  Each AS is represented as a pair
+                    of octets according to the following algorithm:
+
+                        first-byte-of-pair = ASNumber / 256;
+                        second-byte-of-pair = ASNumber & 255;"
+            ::= { bgpPathAttrEntry 4 }
+
+        bgpPathAttrNextHop OBJECT-TYPE
+            SYNTAX     IpAddress
+            MAX-ACCESS read-only
+            STATUS     obsolete
+            DESCRIPTION
+                    "The address of the border router that should
+                    be used for the destination network."
+            ::= { bgpPathAttrEntry 5 }
+
+        bgpPathAttrInterASMetric OBJECT-TYPE
+            SYNTAX     Integer32
+            MAX-ACCESS read-only
+            STATUS     obsolete
+            DESCRIPTION
+                    "The optional inter-AS metric.  If this
+                    attribute has not been provided for this route,
+                    the value for this object is 0."
+            ::= { bgpPathAttrEntry 6 }
+
+
+
+        -- BGP-4 Received Path Attribute Table.  This table contains,
+        -- one entry per path to a network, path attributes
+        -- received from all peers running BGP-4.
+
+        bgp4PathAttrTable OBJECT-TYPE
+            SYNTAX     SEQUENCE OF Bgp4PathAttrEntry
+            MAX-ACCESS not-accessible
+            STATUS     current
+            DESCRIPTION
+                    "The BGP-4 Received Path Attribute Table contains
+                    information about paths to destination networks
+                    received from all BGP4 peers."
+            ::= { bgp 6 }
+
+        bgp4PathAttrEntry OBJECT-TYPE
+            SYNTAX     Bgp4PathAttrEntry
+            MAX-ACCESS not-accessible
+            STATUS     current
+            DESCRIPTION
+                    "Information about a path to a network."
+            INDEX { bgp4PathAttrIpAddrPrefix,
+                    bgp4PathAttrIpAddrPrefixLen,
+                    bgp4PathAttrPeer            }
+            ::= { bgp4PathAttrTable 1 }
+
+        Bgp4PathAttrEntry ::= SEQUENCE {
+            bgp4PathAttrPeer
+                 IpAddress,
+            bgp4PathAttrIpAddrPrefixLen
+                 INTEGER,
+            bgp4PathAttrIpAddrPrefix
+                 IpAddress,
+            bgp4PathAttrOrigin
+                 INTEGER,
+            bgp4PathAttrASPathSegment
+                 OCTET STRING,
+            bgp4PathAttrNextHop
+                 IpAddress,
+            bgp4PathAttrMultiExitDisc
+                 INTEGER,
+            bgp4PathAttrLocalPref
+                 INTEGER,
+            bgp4PathAttrAtomicAggregate
+                 INTEGER,
+            bgp4PathAttrAggregatorAS
+                 INTEGER,
+            bgp4PathAttrAggregatorAddr
+                 IpAddress,
+            bgp4PathAttrCalcLocalPref
+                 INTEGER,
+            bgp4PathAttrBest
+                 INTEGER,
+            bgp4PathAttrUnknown
+                 OCTET STRING
+        }
+
+        bgp4PathAttrPeer OBJECT-TYPE
+            SYNTAX     IpAddress
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The IP address of the peer where the path
+                    information was learned."
+            ::= { bgp4PathAttrEntry 1 }
+        bgp4PathAttrIpAddrPrefixLen OBJECT-TYPE
+            SYNTAX     INTEGER (0..32)
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "Length in bits of the IP address prefix in the
+                    Network Layer Reachability Information field."
+            ::= { bgp4PathAttrEntry 2 }
+
+        bgp4PathAttrIpAddrPrefix OBJECT-TYPE
+            SYNTAX     IpAddress
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "An IP address prefix in the Network Layer
+                    Reachability Information field.  This object
+                    is an IP address containing the prefix with
+                    length specified by bgp4PathAttrIpAddrPrefixLen.
+                    Any bits beyond the length specified by
+                    bgp4PathAttrIpAddrPrefixLen are zeroed."
+            ::= { bgp4PathAttrEntry 3 }
+
+        bgp4PathAttrOrigin OBJECT-TYPE
+            SYNTAX     INTEGER {
+                                 igp(1),-- networks are interior
+                                 egp(2),-- networks learned via EGP
+                                 incomplete(3) -- undetermined
+                               }
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The ultimate origin of the path information."
+            ::= { bgp4PathAttrEntry 4 }
+
+        bgp4PathAttrASPathSegment OBJECT-TYPE
+            SYNTAX     OCTET STRING (SIZE (2..255))
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The sequence of AS path segments.  Each AS
+                    path segment is represented by a triple
+                    <type, length, value>.
+
+                    The type is a 1-octet field which has two
+                    possible values:
+                         1      AS_SET: unordered set of ASs a
+                                     route in the UPDATE message
+                                     has traversed
+                         2      AS_SEQUENCE: ordered set of ASs
+                                     a route in the UPDATE message
+                                     has traversed.
+
+                    The length is a 1-octet field containing the
+                    number of ASs in the value field.
+
+                    The value field contains one or more AS
+                    numbers, each AS is represented in the octet
+                    string as a pair of octets according to the
+                    following algorithm:
+
+                        first-byte-of-pair = ASNumber / 256;
+                        second-byte-of-pair = ASNumber & 255;"
+            ::= { bgp4PathAttrEntry 5 }
+
+        bgp4PathAttrNextHop OBJECT-TYPE
+            SYNTAX     IpAddress
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The address of the border router that should
+                    be used for the destination network."
+            ::= { bgp4PathAttrEntry 6 }
+
+        bgp4PathAttrMultiExitDisc OBJECT-TYPE
+            SYNTAX     INTEGER (-1..2147483647)
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "This metric is used to discriminate between
+                    multiple exit points to an adjacent autonomous
+                    system.  A value of -1 indicates the absence of
+                    this attribute."
+            ::= { bgp4PathAttrEntry 7 }
+
+        bgp4PathAttrLocalPref OBJECT-TYPE
+            SYNTAX     INTEGER (-1..2147483647)
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The originating BGP4 speaker's degree of
+                    preference for an advertised route.  A value of
+                    -1 indicates the absence of this attribute."
+            ::= { bgp4PathAttrEntry 8 }
+
+        bgp4PathAttrAtomicAggregate OBJECT-TYPE
+            SYNTAX     INTEGER {
+                           lessSpecificRrouteNotSelected(1),
+                           lessSpecificRouteSelected(2)
+                       }
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "Whether or not a system has selected
+                    a less specific route without selecting a
+                    more specific route."
+            ::= { bgp4PathAttrEntry 9 }
+
+        bgp4PathAttrAggregatorAS OBJECT-TYPE
+            SYNTAX     INTEGER (0..65535)
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The AS number of the last BGP4 speaker that
+                    performed route aggregation.  A value of zero (0)
+                    indicates the absence of this attribute."
+            ::= { bgp4PathAttrEntry 10 }
+
+        bgp4PathAttrAggregatorAddr OBJECT-TYPE
+            SYNTAX     IpAddress
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The IP address of the last BGP4 speaker that
+                     performed route aggregation.  A value of
+                     0.0.0.0 indicates the absence of this attribute."
+            ::= { bgp4PathAttrEntry 11 }
+
+        bgp4PathAttrCalcLocalPref OBJECT-TYPE
+            SYNTAX     INTEGER (-1..2147483647)
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "The degree of preference calculated by the
+                    receiving BGP4 speaker for an advertised route.
+                    A value of -1 indicates the absence of this
+                    attribute."
+            ::= { bgp4PathAttrEntry 12 }
+
+        bgp4PathAttrBest OBJECT-TYPE
+            SYNTAX     INTEGER {
+                           false(1),-- not chosen as best route
+                           true(2) -- chosen as best route
+                       }
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "An indication of whether or not this route
+                    was chosen as the best BGP4 route."
+            ::= { bgp4PathAttrEntry 13 }
+
+        bgp4PathAttrUnknown OBJECT-TYPE
+            SYNTAX     OCTET STRING (SIZE(0..255))
+            MAX-ACCESS read-only
+            STATUS     current
+            DESCRIPTION
+                    "One or more path attributes not understood
+                     by this BGP4 speaker.  Size zero (0) indicates
+                     the absence of such attribute(s).  Octets
+                     beyond the maximum size, if any, are not
+                     recorded by this object."
+            ::= { bgp4PathAttrEntry 14 }
+
+
+        -- Traps.
+
+        -- note that in RFC 1657, bgpTraps was incorrectly
+        -- assigned a value of { bgp 7 }, and each of the
+        -- traps had the bgpPeerRemoteAddr object inappropriately
+        -- removed from their OBJECTS clause.  The following
+        -- definitions restore the semantics of the traps as
+        -- they were initially defined in RFC 1269.
+
+        -- { bgp 7 } is unused
+
+        bgpTraps          OBJECT IDENTIFIER ::= { bgp 0 }
+
+        bgpEstablished NOTIFICATION-TYPE
+            OBJECTS { bgpPeerRemoteAddr,
+                      bgpPeerLastError,
+                      bgpPeerState      }
+            STATUS  current
+            DESCRIPTION
+                    "The BGP Established event is generated when
+                    the BGP FSM enters the ESTABLISHED state."
+            ::= { bgpTraps 1 }
+
+        bgpBackwardTransition NOTIFICATION-TYPE
+            OBJECTS { bgpPeerRemoteAddr,
+                      bgpPeerLastError,
+                      bgpPeerState      }
+            STATUS  current
+            DESCRIPTION
+                    "The BGPBackwardTransition Event is generated
+                    when the BGP FSM moves from a higher numbered
+                    state to a lower numbered state."
+            ::= { bgpTraps 2 }
+
+        -- conformance information
+
+        bgpMIBConformance OBJECT IDENTIFIER ::= { bgp 8 }
+        bgpMIBCompliances OBJECT IDENTIFIER ::= { bgpMIBConformance 1 }
+        bgpMIBGroups      OBJECT IDENTIFIER ::= { bgpMIBConformance 2 }
+
+        -- compliance statements
+
+        bgpMIBCompliance MODULE-COMPLIANCE
+            STATUS  current
+            DESCRIPTION
+                    "The compliance statement for entities which
+                     implement the BGP4 mib."
+            MODULE  -- this module
+                MANDATORY-GROUPS { bgp4MIBGlobalsGroup,
+                                   bgp4MIBPeerGroup,
+                                   bgp4MIBPathAttrGroup,
+                                   bgp4MIBNotificationGroup }
+            ::= { bgpMIBCompliances 1 }
+
+        -- units of conformance
+
+        bgp4MIBGlobalsGroup OBJECT-GROUP
+            OBJECTS { bgpVersion,
+                      bgpLocalAs,
+                      bgpIdentifier }
+            STATUS  current
+            DESCRIPTION
+                    "A collection of objects providing information
+                     on global BGP state."
+            ::= { bgpMIBGroups 1 }
+
+        bgp4MIBPeerGroup OBJECT-GROUP
+            OBJECTS { bgpPeerIdentifier,
+                      bgpPeerState,
+                      bgpPeerAdminStatus,
+                      bgpPeerNegotiatedVersion,
+                      bgpPeerLocalAddr,
+                      bgpPeerLocalPort,
+                      bgpPeerRemoteAddr,
+                      bgpPeerRemotePort,
+                      bgpPeerRemoteAs,
+                      bgpPeerInUpdates,
+                      bgpPeerOutUpdates,
+                      bgpPeerInTotalMessages,
+                      bgpPeerOutTotalMessages,
+                      bgpPeerLastError,
+                      bgpPeerFsmEstablishedTransitions,
+                      bgpPeerFsmEstablishedTime,
+                      bgpPeerConnectRetryInterval,
+                      bgpPeerHoldTime,
+                      bgpPeerKeepAlive,
+                      bgpPeerHoldTimeConfigured,
+                      bgpPeerKeepAliveConfigured,
+                      bgpPeerMinASOriginationInterval,
+                      bgpPeerMinRouteAdvertisementInterval,
+                      bgpPeerInUpdateElapsedTime }
+            STATUS  current
+            DESCRIPTION
+                    "A collection of objects for managing
+                     BGP peers."
+            ::= { bgpMIBGroups 2 }
+
+        bgp4MIBRcvdPathAttrGroup OBJECT-GROUP
+            OBJECTS { bgpPathAttrPeer,
+                      bgpPathAttrDestNetwork,
+                      bgpPathAttrOrigin,
+                      bgpPathAttrASPath,
+                      bgpPathAttrNextHop,
+                      bgpPathAttrInterASMetric }
+            STATUS  obsolete
+            DESCRIPTION
+                    "A collection of objects for managing BGP
+                     path entries.
+
+                     This conformance group is obsolete,
+                     replaced by bgp4MIBPathAttrGroup."
+            ::= { bgpMIBGroups 3 }
+
+        bgp4MIBPathAttrGroup OBJECT-GROUP
+            OBJECTS { bgp4PathAttrPeer,
+                      bgp4PathAttrIpAddrPrefixLen,
+                      bgp4PathAttrIpAddrPrefix,
+                      bgp4PathAttrOrigin,
+                      bgp4PathAttrASPathSegment,
+                      bgp4PathAttrNextHop,
+                      bgp4PathAttrMultiExitDisc,
+                      bgp4PathAttrLocalPref,
+                      bgp4PathAttrAtomicAggregate,
+                      bgp4PathAttrAggregatorAS,
+                      bgp4PathAttrAggregatorAddr,
+                      bgp4PathAttrCalcLocalPref,
+                      bgp4PathAttrBest,
+                      bgp4PathAttrUnknown }
+            STATUS  current
+            DESCRIPTION
+                    "A collection of objects for managing
+                     BGP path entries."
+            ::= { bgpMIBGroups 4 }
+
+        bgp4MIBNotificationGroup NOTIFICATION-GROUP
+            NOTIFICATIONS { bgpEstablished,
+                            bgpBackwardTransition }
+            STATUS  current
+            DESCRIPTION
+                    "A collection of notifications for signaling
+                    changes in BGP peer relationships."
+            ::= { bgpMIBGroups 5 }
+
+    END
diff --git a/bgpd/ChangeLog b/bgpd/ChangeLog
new file mode 100644
index 0000000..4f7a20e
--- /dev/null
+++ b/bgpd/ChangeLog
@@ -0,0 +1,2368 @@
+2002-10-23  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* bgp_aspath.c (aspath_init): Extend hash size from default to
+	32767.
+	(aspath_key_make): Use unsigned shoft for making hash.  Suggested
+	by: Marc Evans <Marc@SoftwareHackery.Com>
+
+2002-08-19  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* bgp_clist.c (community_entry_free): Fix memory leak of standard
+	extcommunity-list config string.
+
+2002-08-19  Akihiro Mizutani <mizutani@net-chef.net>
+
+	* bgp_route.c (route_vty_out_detail): Fix bug of router-id display
+	when multiple instance is used.
+
+2002-08-18  Akihiro Mizutani <mizutani@net-chef.net>
+
+	* bgpd.c: Make "default-originate" and "maximum-prefix" commands
+	available in peer-group configuration.
+
+2002-08-13  Akihiro Mizutani <mizutani@net-chef.net>
+
+	* bgp_packet.c (bgp_open_send): Put Opt Parm Len 0 when last
+	capability packet cause error or dont-capability-negotiate option
+	is specified.
+
+2002-07-07  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* zebra-0.93 released.
+
+2001-10-28  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (bgp_vty_init): Translate update commands are removed.
+
+2001-10-10  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_static_set): Add workaround for BGP static
+	route announcement when there is no zebra running.
+
+2001-10-08  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (neighbor_remote_as_unicast): Remove "remote-as nlri
+	unicast multicast" commands.
+
+2001-09-14  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_open.c: When we receive capability route-refresh, we should
+	check we send the capability not we receive the capability.
+
+	* bgp_route.c (bgp_network_mask_natural_route_map): network
+	statement route-map is added.
+
+2001-08-31  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* bgp_advertise.c (bgp_advertise_intern): attr must be interned
+	before looking up hash table.
+
+2001-08-30  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* bgpd.h (struct peer): BGP filter is moved from peer_conf to
+	peer.
+
+2001-08-28  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* bgp_nexthop.c (bnc_nexthop_free): Fix next pointer bug.
+	Suggested by: "Hong-Sung Kim" <hoskim@lanbird.co.kr>.
+
+2001-08-26  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* bgp_table.c (bgp_node_create): Clearn memory before use it.
+
+2001-08-24  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* Change to use bgp_table.[ch].
+
+2001-08-23  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* bgpd.c (bgp_init): Add "transparent-as" and
+	"transparent-nexthop" for old version compatibility.
+
+2001-08-23  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgpd.h (struct peer): default-originate route-map is added.
+
+	* bgp_route.c: When self originated route is advertised with
+	attrubute-unchanged, nexthop was not properly set.  This bug is
+	fixed.
+
+2001-08-22  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgpd.c (neighbor_attr_unchanged): transparent-as and
+	transparent-next-hop commands are restructured.  Instead of
+	current transparent-* commands, attribute-unchanged command is
+	introduced.
+
+	neighbor A.B.C.D attribute-unchanged [as-path|next-hop|med]
+
+	(neighbor_default_originate): "default-originate" configuration
+	announce default route even 0.0.0.0/0 does not exists in BGP RIB.
+
+2001-08-19  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* zebra-0.92a released.
+
+2001-08-19  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgpd.c: AF specific soft-reconfiguration inbound commands are
+	added.
+
+2001-08-17  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* bgp_route.c (bgp_show_callback): Do not do community NULL check.
+
+	* bgp_community.c (community_cmp): Add check for commnunity NULL
+	check.
+
+	* bgp_routemap.c (route_match_community): Do not check comunity is
+	NULL.  It may match to community-list "^$".
+
+	* bgp_community.c (community_match): Add check for community is
+	NULL case.
+
+2001-08-17  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgpd.c: AF specific route-reflector-client and
+	route-server-client configuration are added.
+
+2001-08-17  Rick Payne <rickp@ayrnetworks.com>
+
+	* bgp_clist.c (community_match_regexp): Check special ^$ case.
+
+2001-08-17  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_clist.c (community_list_match): Fix bug of community list
+	permit and deny check.
+
+2001-08-16  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_mplsvpn.c (bgp_mplsvpn_init): Add AF specific "nexthop-self"
+	command.
+
+2001-08-15  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgpd.h (PEER_FLAG_SEND_COMMUNITY): Per AF based configuration
+	flag is introduced.
+
+	* bgp_mplsvpn.c (bgp_mplsvpn_init): VPNv4 filtering is added.
+
+2001-08-15  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* zebra-0.92 released.
+
+2001-08-13  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* bgpd.c (bgp_delete): "no router bgp" free static, aggregate, rib
+	table properly.
+
+2001-08-12  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* bgp_route.c (bgp_node_safi): Return SAFI of current node.
+	(bgp_config_write_network_vpnv4): VPNv4 static configuration
+	display.
+
+2001-08-11  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* bgpd.c (no_bgp_ipv4_multicast_route_map): Add IPv4 multicast
+	node filter commands.
+
+2001-08-11  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.h (PEER_FLAG_IGNORE_LINK_LOCAL_NEXTHOP): Add
+	"ignore-link-local-nexthop" flag for ignore link-local nexthop for
+	IPv6.
+
+2001-08-07  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* bgpd.c (address_family_ipv4_multicast): "address-family ipv4
+	multicast" is added.
+	(address_family_ipv6_unicast): "address-family ipv6 unicast" is
+	added.
+	
+2001-08-07  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_route.c (bgp_process): Use flag instead of as_selected
+	memeber in struct bgp_info.
+
+	* bgp_route.h (struct bgp_info): Remove as_selected memeber from
+	struct bgp_info.
+
+2001-07-31  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* bgp_route.c (bgp_announce_check): Enclose sending time AS loop
+	check code with #ifdef BGP_SEND_ASPATH_CHECK.
+
+2001-07-29  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* bgp_packet.c (bgp_withdraw_send): Simplify address family check.
+
+	* bgpd.h (BGP_INFO_HOLDDOWN): Introduce new macro to check BGP
+	information is alive or not.
+
+	* bgp_community.c: Use community_val_get() on all OS.
+
+2001-07-24  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* bgp_route.c (bgp_announce_check): Simplify set next-hop self
+	check.
+
+2001-07-24  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_route.c (bgp_announce_check): To route server clients, we
+	announce AS path, MED and nexthop transparently.
+
+2001-06-21  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_routemap.c (route_set_atomic_aggregate_free): Do not call
+	XFREE.  No memory is allocated in
+	route_set_atomic_aggregate_compile().
+
+2001-06-21  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_routemap.c (bgp_route_map_init): `match nlri` and `set nlri`
+	are replaced by `address-family ipv4` and `address-family vpnvr'.
+
+2001-06-19  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_withdraw): Add check for BGP_PEER_CONFED.
+	Reported by Rick Payne <rickp@rossfell.co.uk>.
+
+2001-06-17  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_zebra.c (bgp_zebra_announce): When global IPv6 nexthop is
+	empty, use socket's remote address for the nexthop.
+
+2001-06-04  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* bgpd.c (peer_delete): Fix memory leak.  Reported by Yosi Yarchi
+	<Yosi_Yarchi@KereniX.com>
+
+2001-06-01  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* bgpd.c (bgp_delete): Fix memory leak.  Reported by Yosi Yarchi
+	<Yosi_Yarchi@KereniX.com>
+
+2001-05-27  Kunihiro Ishiguro  <kunihiro@ipinfusion.com>
+
+	* bgp_route.c (bgp_route_clear_with_afi_vpnv4): Use next instead
+	of ri->next.
+
+	* bgp_packet.c (bgp_withdraw_send): MPLS/VPN withdraw takes effect
+	when HAVE_IPV6 is not defined.
+
+2001-03-07  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgpd.c (peer_timers_set): Adjust keepalive timer to fit less
+	than holdtime / 3.
+	(bgp_confederation_peers_unset): Only set peer->local_as when
+	confederation is enabled.
+	(bgp_timers): Add "timers bgp <0-65535> <0-65535>" command.
+
+	* bgp_route.c (bgp_announce_check): Set med of redistributed route
+	when it is announced to EBGP peer.
+
+2001-03-06  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgp_nexthop.c (bgp_scan_ipv4): bgp_scan() call bgp_process() for
+	all prefixes.
+
+2001-03-06  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_attr.c (bgp_attr_origin): When bgpd send NOTIFICATION with
+	erroneous attribute (type, length and value), it does include
+	attribute flags field.
+
+2001-02-21  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgp_route.c (bgp_announce_check): The route reflector is not
+	allowed to modify the attributes of the reflected IBGP routes.
+
+2001-02-20  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgp_route.c (bgp_info_cmp): During path seleciton, BGP
+	confederation peer is treated as same as IBGP peer.
+
+2001-02-19  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_redistribute_add): Initialize attr_new with
+	attr.  Call aspath_unintern when return from this function.
+
+2001-02-19  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgpd.c (bgp_router_id_set): Reset BGP peer when router-id is
+	changed.
+
+2001-02-18  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgp_packet.c (bgp_open_receive): When user configure holdtimer,
+	do not refrect the value to current session.
+
+2001-02-16  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_aggregate_delete): Set BGP_INFO_ATTR_CHANGE to
+	suppress route withdraw.
+
+	* bgp_damp.c (bgp_damp_init): Fix bug of flap dampening.
+
+2001-02-16  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgp_aspath.c (aspath_make_str_count): Use ',' for separator for
+	AS_SET and AS_CONFED_SET.
+
+2001-02-15  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_process): Do not consider suppress route.
+
+	* bgp_aspath.c (aspath_aggregate_as_set_add): Reset asset when
+	aspath->data is realloced.
+
+2001-02-15  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgp_attr.c (bgp_attr_aggregate_intern): Do not set atomic
+	aggregate when using as-set.
+
+2001-02-14  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgpd.c (bgp_confederation_peers_unset): Set peer's local-as
+	correctly.
+
+	* bgp_route.c (bgp_update): Just ignore AS path loop for
+	confederation peer.
+
+2001-02-10  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_aggregate_set): Add as_set argument.
+	(bgp_aggregate_unset): Remove summary_only argument.
+	(aggregate_address_as_set): New commands.
+	"aggregate-address A.B.C.D/M as-set"
+	"no aggregate-address A.B.C.D/M as-set"
+
+2001-02-08  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgp_route.c (bgp_announce_check): Do not modify nexthop when the
+	route is passed by route reflector.
+
+2001-02-08  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c: "no bgp dampening" with argument.
+	(bgp_announce_check): Do not modify nexthop when the route is
+	passed by route reflector.
+
+2001-02-07  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgpd.c (neighbor_passive): Change "neighbor NEIGHBOR remote-as
+	ASN passive" to "neighbor NEIGHBOR passive".
+	(bgp_announce_check): Check well-known community attribute even
+	when "no neighbor send-community" is set.
+
+2001-02-03  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_fsm.c (bgp_establish): Do not send keepalive at established
+	time when keepalive timer is configured as zero.
+
+2001-02-01  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_attr.c (bgp_attr_check): When peer is IBGP peer, local
+	preference is well-known attribute.
+
+2001-01-30  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* zebra-0.91 is released.
+
+	* bgp_attr.h (struct attr): Comment out DPA value.
+	(struct attr): Change refcnt type from int to unsinged long.
+
+	* bgp_attr.c (attrhash_key_make): Likewise.
+	(attrhash_cmp): Likewise.
+	(bgp_attr_dpa): Likewise.
+
+2001-01-30  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgp_route.c (bgp_info_cmp): Make route selection completely same
+	as Cisco's.
+
+2001-01-30  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_attr.h (BGP_ATTR_FLAG_OPTIONAL): Rename old ATTR_FLAG_* to
+	BGP_ATTR_FLAG_* to clarify meenings.
+
+2001-01-30  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgp_route.c (route_vty_out): Display argument to suppress same
+	prefix information display.
+	(route_vty_out_route): Don't display mask information for
+	classfull network.
+
+2001-01-30  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_attr.h (SET_BITMAP): Simple bitmapping macros.
+
+	* bgp_attr.c (bgp_attr_parse): Use bitmap for attribute type
+	check.
+
+2001-01-29  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_attr.c (bgp_mp_reach_parse): Enclose loggin with BGP_DEBUG.
+	(bgp_attr_parse): Comment out well-known attribute check.
+
+2001-01-28  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_static_unset): Link-local IPv6 address can't be
+	used for network advertisement.
+	(nlri_parse): When link-local IPv6 address NLRI comes from
+	remote-peer, log the information then simply ignore it.
+
+	* bgp_zebra.c (zebra_read_ipv6): Link-local IPv6 address is not
+	redistributed.
+
+	* bgp_route.c (bgp_update): Check IPv6 global nexthop
+	reachability.
+
+2001-01-26  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_update): Check nexthop points local address or
+	not.
+	(bgp_static_update_vpnv4): Set valid flag.
+
+	* bgp_attr.c (bgp_attr_parse): Duplicate attribute check.
+	(bgp_attr_parse): Well-known attribute check.
+
+	* bgp_open.c (bgp_auth_parse): Authentication is not yet supported.
+
+	* bgp_packet.c (bgp_valid_marker): Check marker is synchronized.
+
+	* bgpd.c (clear_bgp): Send NOTIFICATION Cease when SEND_CEASE is
+	defined.
+
+	* bgp_snmp.c (bgp4PathAttrTable): Fix compile error.
+
+2001-01-24  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (bgp_network_import_check): New command for IGP network
+	check.
+
+2001-01-23  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_nexthop.c (bgp_scan): Run bgp_process when IGP metric is
+	changed.  Call bgp_process once for each node.
+
+2001-01-23  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgp_route.c (bgp_info_cmp): Add IGP metric comparison.
+
+2001-01-23  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_info_cmp): Add IGP metric comparison.
+
+	* bgp_nexthop.c (bgp_nexthop_lookup): Set IGP metric for valid
+	IBGP route.
+
+2001-01-23  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgp_route.c (show_ip_bgp_prefix_longer): Add new commands.
+	"show ip bgp A.B.C.D/M longer-prefixes"
+	"show ip bgp ipv4 (unicast|multicast) A.B.C.D/M longer-prefixes"
+	"show ipv6 bgp X:X::X:X/M longer-prefixes"
+	"show ipv6 mbgp X:X::X:X/M longer-prefixes"
+	
+2001-01-20  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgp_route.c (show_ip_bgp_cidr_only): Add new commands.
+	"show ip bgp cidr-only"
+	"show ip bgp ipv4 (unicast|multicast) cidr-only"
+	
+2001-01-18  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgp_route.c (bgp_update): AS path lookup check is done in
+	bgp_update() not in attr_parse().
+
+2001-01-18  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_update): Call bgp_aggregate_decrement() just
+	before bgp_attr_unintern().
+
+2001-01-17  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_update): Now intern is performed very last part
+	of the BGP packet update procedure.
+
+2001-01-17  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgp_route.c (bgp_update): When implicit withdraw occur, reuse
+	existing bgp_info structure.
+
+2001-01-17  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_aggregate_decrement): Fix bug of aggregate
+	address matching method.
+	(bgp_update): 
+
+	* bgp_nexthop.c (bgp_nexthop_onlink): Separate EBGP nexthop onlink
+	check and IBGP nexthop route check.
+
+2001-01-16  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgp_route.h (BGP_INFO_ATRR_CHANGED): Added for track attribute
+	change.
+
+2001-01-16  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.h (struct bgp_info): Remove selected flag.  Use
+	BGP_INFO_SELECTED for flags instead.
+	(struct bgp_info): Remove valid flag.  Use BGP_INFO_VALID for
+	flags instead.
+	(struct bgp_info): Add igpmetric for IBGP route nexthop IGP
+	metric.
+	(struct bgp_info_tab): Struct bgp_info_tag is integrated into
+	struct bgp_info.
+	(BGP_INFO_ATRR_CHANGED): Added for track attribute change.
+
+	* bgp_community.c (community_val_get): gcc-2.95 on
+	sparc-sun-solaris cause crush.  This function is for avoid the
+	crush.
+
+2001-01-15  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_packet.c (bgp_open_receive): Translated peer's packet_size
+	clear bug is fixed.
+
+2001-01-14  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgp_packet.c (bgp_open_receive): Return notification with
+	supported version number.
+
+2001-01-13  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (bgp_show_summary): Display AS path and community
+	entries.  Suggested by: "Matt Ranney" <mjr@ranney.com>.
+
+	* bgp_packet.c (bgp_read_packet): Fix bug of unblocking BGP socket
+	read.  When BGP packet read is partial, we must get size and type
+	from packet again.
+
+2001-01-12  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgp_route.c (bgp_update): Do not unset BGP_INFO_HISTORY flag.
+	(bgp_update): When there is a history entry increment route count.
+	(bgp_damp_set): Check BGP_CONFIG_DAMPENING flag.
+
+	* bgp_damp.c (bgp_damp_withdraw): Set status to
+	BGP_DAMP_DISCONTINUE.
+
+2001-01-11  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_attr.c (bgp_mp_reach_parse): Fix warning code when second
+	IPv6 nexthop is not link-local addresss.
+
+2001-01-11  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgp_damp.c (bgp_config_write_damp): Smart flap dampening
+	configuration display.
+	(bgp_damp_info_print): Display elapsed time from flap started.
+
+	* bgp_damp.h (struct bgp_damp_info): Add flap start time.
+
+	* bgpd.c (peer_create): Set last read time.
+	(bgp_show_peer): Display last read time.
+	(bgp_show_summary): Use BGP_CONFIG_DAMPENING flag to check
+	configuration.
+	
+	* bgpd.h (BGP_CONFIG_DAMPENING): Add new configuration option.
+	(struct peer): Add last read time member.
+	(BGP_VERSION_MP_4): Remove obsolete definition.
+
+2001-01-10  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_nexthop.c: Remove OLD_RIB codes.
+
+	* bgp_route.c (bgp_process): Likewise.
+
+	* zebra-0.90 is released.
+
+	* bgp_route.h (BGP_INFO_HISTORY): Remove damped member from struct
+	bgp_info.  Instead of that use BGP_INFO_DAMPED flag.
+	(struct bgp_info): Remove invalid member from struct bgp_info.
+	Instead of that use BGP_INFO_HISTORY flag.
+
+2001-01-10  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgp_damp.c (bgp_damp_info_print): New function to display
+	dampening status.
+	(DEFAULT_HARF_LIFE): Define default value.
+	(DEFAULT_REUSE): Likewise.
+	(DEFAULT_SUPPRESS): Likewise.
+	(bgp_config_write_damp): When config value is same as default
+	value, simply display "bgp dampening" to configuration.
+
+	* bgp_damp.h (struct bgp_damp_info): Add flap member.
+
+	* bgp_route.h (struct bgp_info): Added for BGP flap dampening
+	history status.
+
+2001-01-10  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_nexthop.c (bgp_connected_add): Point-to-point connected
+	address is properly handled.
+	(bgp_connected_delete): Likewise.
+
+	* bgp_route.c (bgp_route_init): Turn off BGP Flap dampening code
+	until it works fine.
+
+2001-01-09  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (bgp_show_summary): Add BGP_VERSION_MP_4 case.
+
+	* bgp_route.c (bgp_update): When this is not damped route, clear
+	ri pointer.
+
+2001-01-09  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_main.c: Add "-n" no_kernel option to not install route to
+	kernel.  Suggested by: "Matt Ranney" <mjr@ranney.com>
+
+2001-01-09  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_nexthop.c (bgp_connected_add): Revert point-to-point
+	connected route patch.  Reported by ruud@ruud.org (Ruud de Rooij)
+
+	* bgp_damp.c (bgp_config_write_damp): Add configuration display
+	function.
+
+	* bgp_route.c (bgp_info_free): Set NULL to BGP dampening
+	information when BGP info structure is freed.
+	(bgp_info_cmp): Check damped flag.
+	(bgp_announce_check): Damped route is not announced.
+
+2001-01-09  "Akihiro Mizutani" <mizutani@dml.com>
+
+	* bgpd.c (neighbor_capability_route_refresh): Change "neighbor
+	route-refresh" command to "neighbor capability route-refresh".
+	(clear_bgp_soft_in): Change soft-reconfig method.
+
+	clear ip bgp <neighbor> soft in
+        --------------------------------------
+        Try stored cache first then route-refresh
+
+        clear ip bgp <neighbor> in
+        ---------------------------------
+        Try route-refresh first then try to use stored cache
+
+2001-01-09  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_nexthop.c (bgp_connected_add): Check point-to-point
+	connected route.  Reported by ruud@ruud.org (Ruud de Rooij)
+
+2001-01-08  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_nexthop.c (bgp_nexthop_lookup): When IBGP nexthop is
+	changed, refresh it.
+
+2001-01-04  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.h (struct bgp_info_tag): Add as_selected to
+	bgp_info_tag.
+
+2001-01-03  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.h (struct bgp_info_tag): Add damped and bgp_damp_info
+	member for BGP flap dampening.
+
+	* bgp_damp.c: New file is added.
+
+	* bgp_damp.h: Likewise.
+
+2001-01-01  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.h (BGP_VTYSH_PATH): Change "/tmp/bgpd" to "/tmp/.bgpd".
+
+2000-12-29  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_nexthop.c (zlookup_connect): Change to use UNIX domain
+	socket for zebra communication.
+
+2000-12-29  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_route.c (bgp_process): Fix "bgp deterministic-med" process.
+
+2000-12-27  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_route.c (bgp_process): Add "bgp deterministic-med" process.
+
+2000-12-25  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_route.c (bgp_info_cmp): Use ntohl comparing router ID.
+
+2000-12-18  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_route.c (bgp_info_cmp): When over three same prefix exit,
+	withdrawing best prefix perform router ID comparison.
+
+2000-12-15  Akihiro Mizutani  <mizutani@dml.com>
+
+	* bgp_route.c (bgp_info_cmp): Do not compare router ID when the
+	routes comes from EBGP peer.  When originator ID is same, take
+	shorter cluster-list route.  If cluster-list is same take smaller
+	IP address neighbor's route.
+
+	* bgpd.c (bgp_bestpath_aspath_ignore): Add "bgp bestpath as-path
+	ignore" command.  When this option is set, do not concider AS path
+	length when route selection.
+	(bgp_bestpath_compare_router_id): Add "bgp bestpath
+	compare-routerid".  When this option is set, compare router ID
+	when the routes comes from EBGP peer.
+	
+2000-12-15  Akihiro Mizutani  <mizutani@dml.com>
+
+	* bgp_route.c (bgp_info_cmp): Compare originator ID when it is
+	available.
+
+2000-12-14  Akihiro Mizutani  <mizutani@dml.com>
+
+	* bgp_packet.c (bgp_notify_receive): Disply received Notify data
+	information.
+
+2000-12-14  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_filter.c (as_filter_free): Use MTYPE_AS_FILTER_STR to make
+	it sure the memory is freed.
+
+	* bgp_route.c (route_vty_out_detail): Do not use AF_INET6 outside
+	HAVE_IPV6.
+
+2000-12-08  Akihiro Mizutani  <mizutani@dml.com>
+
+	* bgp_packet.c (bgp_notify_send_with_data): Store BGP notification
+	data part.
+
+	* bgp_network.c (bgp_accept): When BGP connection comes from
+	unconfigured IP address, close socket immediately.
+
+	* bgpd.c: Fix some display format.
+
+2000-11-29  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_packet.c (bgp_keepalive_send): Delete duplicate
+	bgp_packet_set_size () call.
+
+2000-11-28  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_packet.c (bgp_read_packet): Remove debug codes.
+
+2000-11-27  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_snmp.c (write_bgpPeerTable): Add SNMP set method routine.
+
+	* bgp_fsm.c (bgp_stop): Use fsm_change_status to change peer's
+	status.
+	(bgp_establish): Likewise.
+
+2000-11-26  Akihiro Mizutani  <mizutani@dml.com>
+
+	* bgp_open.c: Fix error messages.
+
+2000-11-25  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_fsm.c (bgp_establish): Call BGP trap when the peer is
+	established.
+	(bgp_stop): Call BGP trap when the peer is dropped.
+
+2000-11-24  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_snmp.c (bgp4PathAttrTable): Return BGP path attribute table.
+
+	* bgpd.h (struct peer): Add update_time for track last update
+	received time.
+
+	* bgp_packet.c (bgp_notify_receive): Preserv notify code and sub
+	code in any case.
+
+	* bgp_snmp.c (bgpPeerTable): Return remote router ID instead of
+	peering IP address.
+	(bgpPeerTable): Return actual BGP version number.
+
+2000-11-22  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_debug.c (bgp_notify_print): Notify data length display bug
+	is fixed.
+
+2000-11-16  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_nexthop.c (zlookup_connect): When UNIX domain connection to
+	zebra is enabled, use the method.
+
+2000-11-16  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgpd.c: Revise debug message output.
+
+2000-11-15  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_clist.c (ip_community_list): Fix bug of string comparison.
+
+2000-11-14  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_community.c (community_match): Fix bug of memcmp return
+	value check.
+
+2000-11-07  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_clist.c (community_list_match_exact): Add check for
+	entry->style is COMMUNITY_LIST.
+	(community_match_regexp): Apply new com_nthval macro.
+
+2000-11-07  Rick Payne <rickp@rossfell.co.uk>
+
+	* bgp_routemap.c (route_set_community_delete): "set
+	community-delete COMMUNITY-LIST" is added.
+
+	* bgp_community.c (community_del_val): Delete one community.
+	(community_delete): Delete all community included in list.
+	(community_match): Fix bug of matching community value.
+
+	* bgp_clist.c (community_entry_free): Free community regular
+	expression.
+	(community_entry_make): Default style is COMMUNITY_LIST.
+	(community_entry_lookup): Make it sure style is COMMUNITY_LIST.
+	(community_entry_regexp_lookup): New function for community
+	regular expression lookup.
+	(community_match_regexp): New function.
+	(community_delete_regexp): New function.
+	(community_list_delete_entries): New function.
+	(community_list_match): Add COMMUNITY_REGEXP treatment.
+	(community_list_match_exact): Likewise.
+	(config_write_community): Write community list according to
+	entry->style.
+
+2000-11-07  Rick Payne <rickp@rossfell.co.uk>
+
+	* bgp_attr.c (bgp_attr_aspath): AS path first AS check.
+
+	* bgp_clist.c (struct community_entry): Add style, regexp, reg to
+	community_entry.
+
+2000-11-06  Rick Payne <rickp@rossfell.co.uk>
+
+	* bgp_aspath.c (aspath_firstas_check): AS path first AS check.
+
+	* bgpd.c (bgp_enforce_first_as): New command "bgp
+	enforce-first-as".
+
+	* bgpd.h (BGP_CONFIG_ENFORCE_FIRST_AS): Add new flag.
+
+2000-11-06  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_community.c (community_compare): Copy byte stream data to
+	actual value instead of using type casting hack.
+	(community_add_val): Likewise.
+	(community_uniq_sort): Likewise.
+	(community_print): Likewise.
+	(community_print_vty): Likewise.
+	(community_include): Use memcmp to compare community value.
+
+	* bgp_community.h (com_lastval): com_lastval and com_nthval macro
+	return pointer.
+
+2000-11-06  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgpd.h (struct peer): Add established and dropped member for
+	count peering up/down statistics.
+
+	* bgpd.c (bgp_show_peer): Display peering up/down statistics.
+
+	* bgp_fsm.c (bgp_establish): Increment established count.
+	(bgp_stop): Increment dropped count.
+
+	* bgp_packet.c (bgp_notify_receive): Increament notify count.
+
+2000-11-1  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_fsm.c: Fix bug of holdtimer is not reset when bgp cleared. 
+
+2000-10-31  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.h: Static bit flag is set by (1 << DIGIT).
+
+2000-10-24  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_ecommunity.c (ecommunity_dup): Extended community display
+	format fix.
+
+2000-10-24  Arkadiusz Miskiewicz <misiek@pld.org.pl>
+
+	* bgp_network.c (bgp_serv_sock_addrinfo): Use gai_strerror.
+	(bgp_serv_sock_addrinfo): Check address family.
+
+2000-10-23  Jochen Friedrich <jochen@scram.de>
+
+	* bgp_snmp.c: bgp_oid and bgpd_oid are used in smux_open after it
+	is registered.  So those variables must be static.
+
+2000-10-23  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_routemap.c (route_match_ip_next_hop): Change "match ip
+	next-hop" argument from IP address to access-list name.
+	Remove zebra-0.88 compatibility commands.
+        "match ip prefix-list WORD"
+        "match ipv6 prefix-list WORD"
+	
+2000-10-23  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_routemap.c (route_match_ipv6_next_hop_compile): Fix bug of
+	passing the pointer to the pointer of struct in6_addr instead of
+	the pointer of struct in6_addr in "match ipv6 next-hop" command.
+
+	* bgp_route.c (bgp_announce_check): Enclose IPv6 part with
+	HAVE_IPV6.
+
+2000-10-20  Jasper Wallace <jasper@ivision.co.uk>
+
+	* bgp_snmp.c (bgpPeerTable): ntohs missing bug is fixed.  Change
+	to use linklist.c.  Define COUNTER32 as ASN_COUNTER.
+
+2000-10-18  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_announce_check): attr->nexthop empty check
+	should be done by attr->nexthop.s_addr instead of strcmp.
+
+2000-10-18  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_zebra.c (zebra_read_ipv4): Pass nexthop value to
+	bgp_redistribute_add().
+
+	* bgp_nexthop.c (bgp_multiaccess_check_v4): New function for
+	checking IPv4 multiaccess nexthop.
+
+	* bgp_route.c (bgp_announce_check): In case of the nexthop is
+	reachable on multiaccess media, do not change nexthop.
+	(bgp_redistribute_add): Set nexthop when the value is passed.
+
+2000-10-17  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_fsm.c (bgp_timer_set): If peer is passive mode, do not set
+	connect timer.
+	(bgp_start): If the peer is passive mode, force to move to Active
+	mode.
+
+2000-10-17  Horms <horms@vergenet.net>
+
+	* bgp_debug.c (debug_bgp_fsm): Fix typo.
+
+2000-10-17  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_route.c: "show ipv6 bgp" route display improvement.
+
+2000-10-03  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (neighbor_routes): Allocate sockunion for callback
+	function.
+	(bgp_show_neighbor_route): Remove static declaration for union
+	sockunion.
+
+	* bgpd.c (peer_update_source_set): Clean previously allocated
+	memory before allocate new one.
+
+2000-10-03  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_route.c (neighbor_routes): Add show neighbor's routes
+	command.
+	"show ip bgp neighbors (A.B.C.D|X:X::X:X) routes"
+	"show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) routes"
+	"show ipv6 bgp neighbors (A.B.C.D|X:X::X:X) routes"
+	"show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X) routes"
+
+2000-10-02  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* zebra-0.89 is released.
+
+2000-10-02  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgpd.c: "bgp deterministic-med" command is added.
+
+2000-10-02  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_nexthop.c (bgp_connected_add): Apply mask for connected
+	route addition and deletion.
+
+2000-09-29  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_aspath.c (aspath_cmp_left): Skip confederation AS segment
+	when comparing leftmost AS number.
+
+2000-09-29  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgpd.c (peer_route_reflector): Route reflector can be set for
+	IBGP peer.
+	(bgp_distribute_set): Fix bug of string check for (in|out).
+	(bgp_show_summary): Display total neighbor count.
+
+2000-09-28  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_attr.c (bgp_packet_attribute): Only add cluster_list and
+	originator for clinet to client routes.
+	(bgp_packet_attribute): Add new cluster_list to the beginning of
+	existing cluster_list.
+	(bgp_packet_attribute): Fix bug of originator is rewritten even
+	when originator is already set.
+
+2000-09-27  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (bgp_client_to_client_reflection): Add new command.
+	"no bgp client-to-client reflection"
+	"bgp client-to-client reflection"
+
+	* bgpd.h (BGP_CONFIG_NO_CLIENT_TO_CLIENT): Add new definition.
+
+2000-09-26  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_packet.c (bgp_read): Make BGP packet read to non-blocking
+	read.
+	(bgp_read_packet): Likewise.
+	(bgp_read_packet): When errono is EAGAIN, try to read it again.
+
+	* bgp_fsm.c (bgp_stop): Clear packet size and read buffer.
+
+2000-09-26  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_routemap.c: Configuration of prefix-list match is shown as
+	"match ip address prefix-list <WORD>".  Old configuration "match
+	ip prefix-list <WORD>" is left for compatibilitty.
+
+2000-09-25  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgpd.h (BGP_CONFIG_MED_MISSING_AS_WORST): Changed from
+	BGP_CONFIG_MISSING_AS_WORST.
+
+	* bgpd.c (bgp_bestpath_med): Change missing-as-worst syntax.
+	Old "bgp bestpath missing-as-worst"
+	New "bgp bestpath med missing-as-worst"
+
+2000-09-24  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_route.c: Compare MED properly in case of CONFED-IBGP.
+
+2000-09-21  steve@Watt.COM (Steve Watt)
+
+	* bgp_debug.h: Do not declare debug variables conf_bgp_debug_* and
+	term_bgp_debug_*.
+
+	* bgp_debug.c: Declare variables here.
+
+2000-09-21  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgpd.c: MBGP soft-reconfiguration command is added.
+	clear ip bgp x.x.x.x ipv4 (unicast|multicast) in
+	clear ip bgp x.x.x.x ipv4 (unicast|multicast) out
+	clear ip bgp x.x.x.x ipv4 (unicast|multicast) soft
+	clear ip bgp <1-65535> ipv4 (unicast|multicast) in
+	clear ip bgp <1-65535> ipv4 (unicast|multicast) out
+	clear ip bgp <1-65535> ipv4 (unicast|multicast) soft
+	clear ip bgp * ipv4 (unicast|multicast) in
+	clear ip bgp * ipv4 (unicast|multicast) out
+	clear ip bgp * ipv4 (unicast|multicast) soft
+
+	Change "clear ip bgp vpnv4 x.x.x.x soft" command to
+	"clear ip bgp x.x.x.x vpnv4 unicast soft".
+
+	"bgp bestpath med confed" command is added.
+	
+	* bgpd.h (BGP_CONFIG_MED_CONFED): Add New definition.
+
+2000-09-18  Rick Payne <rickp@rossfell.co.uk>
+
+	* bgpd.c (bgp_show_peer): Fix misplaced #endif.
+
+2000-09-12  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgpd.c (bgp_default_local_preference): Add "bgp default
+	local-preference" command.
+
+	* bgp_nexthop.c (no_bgp_scan_time): Add "no bgp scan-time"
+	command.
+
+2000-09-10  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_zebra.c (bgp_zebra_announce): BGP confederation peer's routes
+	are passed to zebra like IBGP route.
+
+2000-09-10  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgpd.c (bgp_config_write_peer): Make it consistent passive
+	configuration.
+
+	* bgp_route.c: Community match command is added.
+	"show ip bgp community <val>"
+	"show ip bgp community <val> exact-match"
+
+2000-09-08  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_nexthop.c (bgp_nexthop_lookup): ebgp-multihop routes are
+	treated as IBGP routes.
+
+2000-09-08  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_route.c (bgp_show_route): When local-AS community route is
+	selected, display "not advertised outside local AS" to "show ip
+	route A.B.C.D" output.
+	(show_ip_bgp_ipv4_filter_list): Add below four commands.
+	"show ip bgp ipv4 (unicast|multicast) filter-list WORD"
+	"show ip bgp ipv4 (unicast|multicast) community"
+	"show ip bgp ipv4 (unicast|multicast) community-list WORD"
+	"show ip bgp ipv4 (unicast|multicast) community-list WORD exact-match"
+	
+	* bgp_clist.c (community_list_match_exact): Community exact match
+	function.
+
+2000-09-07  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_update): Add peer's ttl check.
+
+	* bgpd.h (struct peer): Structure member refresh is renamed to
+	refresh_adv.
+
+	* bgpd.c (clear_bgp_soft_in): Check PEER_FLAG_ROUTE_REFRESH flag
+	when soft reconfiguration is performed.
+
+	* bgp_zebra.c (bgp_zebra_announce): When the peer is EBGP and
+	ebgp-multiphop is set, set ZEBRA_FLAG_INTERNAL for nexthop lookup.
+
+	* bgp_route.h (struct bgp_info_tag): Add valid flag.
+
+2000-08-25  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgpd.c: Add AS base BGP soft reconfiguration.
+
+	* bgp_route.c: When no-advertise or no-export route is selected,
+	"show ip bgp" display "not advertised to EBGP peer" or "not
+	advertised to any peer" message.
+	
+2000-08-17  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* zebra-0.88 is released.
+
+	* bgp_dump.c (dump_bgp_routes): Change "dump bgp routes" to "dump
+	bgp route-mrt" to support MRT specific dump format.
+
+	* bgpd.c (bgp_init): "clear ip bgp vpnv4 soft {in,out}" command is
+	added.
+
+	* bgp_route.c (bgp_update): Currently nexthop check is only works
+	for IPv4.
+
+2000-08-17  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgpd. (clear_ip_bgp_all_soft): Add "clear ip bgp * soft" for
+	both inbound and outbound soft reconfiguration.
+
+2000-08-17  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (clear_ip_bgp_peer_soft_out): Add soft-reconfiguration
+	outbound.
+	(peer_new): Set route-refresh flag.
+
+2000-08-16  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgpd.c: "no bgp router-id A.B.C.D" alias is added.  "no bgp
+	cluster-id A.B.C.D" alias is added.  " bgp cluster-id
+	<1-4294967295>" alias is added.  "clear ip bgp * soft in" command
+	is added.  "clear ip bgp A.B.C.D in" alias is added.  "clear ip
+	bgp * in" alias is added.
+
+2000-08-16  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_update): Add soft_reconfig flag.  When the flag
+	is set do not install the route into Adj-RIBs-In.
+	(bgp_update): Perform implicit withdraw before filtering of the
+	route.
+
+	* bgp_packet.c (bgp_read): draft-ietf-idr-bgp-route-refresh-01.txt
+	capability code and BGP message can be accepted.
+
+	* bgp_open.c (bgp_capability_parse): Likewise.
+
+	* bgp_route.c (bgp_refresh_table): New function for route refresh.
+	(bgp_refresh_rib): Likewise.
+
+	* bgpd.c (bgp_show_peer): Display route refresh status.
+
+	* bgp_route.c (bgp_aggregate_add): Add check for the route
+	validness.
+	(bgp_aggregate_delete): Likewise.
+
+2000-08-15  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_nexthop.c (bgp_scan): Care for aggregate route when the
+	route become inaccessible.
+
+2000-08-15  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_route.c (show_ip_bgp_prefix): "show ip bgp A.B.C.D/M"
+	command is added.
+
+2000-08-15  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_zebra.c (bgp_interface_up): Register connected route.
+	(bgp_interface_down): Unregister connected route.
+
+2000-08-14  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.h (struct bgp_info): Add distance to the structure.
+
+	* bgp_route.c (bgp_aggregate_increment): Aggregate route only
+	match to smaller prefixlen route not match same prefixlen route.
+	(bgp_aggregate_decrement): Likewise.
+	(bgp_aggregate_add): Likewise.
+	(bgp_aggregate_delete): Likewise.
+	(bgp_network_backdoor): Add backdoor network configuration.
+
+	* bgpd.h (struct bgp ): Add distance_{ebgp,ibgp,local} for store
+	configuration distance value.
+
+	* bgp_route.c (bgp_update): Filter EBGP route which has non
+	connected nexthop.
+
+	* bgp_attr.c (bgp_attr_aggregate_intern): New function for
+	aggregate route.  Set origin to IGP.  Set atomic aggregate flag.
+	Set aggregator AS and address.
+	(bgp_attr_aggregate_intern): Check BGP_CONFIG_CONFEDERATION when
+	filling aggregator_as.
+
+	* bgp_route.c (bgp_process): Delete suppress check for install
+	suppressed route into local routing table.
+	(bgp_aggregate_increment): Use bgp_attr_aggregate_intern() instead
+	of bgp_attr_default_intern ().
+	(bgp_aggregate_add): Likewise.
+
+	* bgpd.c (bgp_get): Call bgp_if_update_all() after BGP instance is
+	created.  This is for avoid 0.0.0.0 router-id.
+
+2000-08-13  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_route.c (route_vty_out_detail): Display "valid" when the
+	route is valied.  Display "aggregated" when the route is
+	aggregated.  "Advertisements suppressed by an aggregate" is
+	displayed when the route is suppressed.
+	(bgp_info_cmp): Prefer EBGP than Confed-EBGP.
+
+2000-08-10  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_route.c (route_vty_out_detail): Display format change.
+
+2000-08-06  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_update): Only AFI_IP nexthop check is enabled.
+
+	* bgpd.c (bgp_delete): Delete static route before delete peer
+	configuration.
+
+2000-08-02  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c: Include bgpd/bgp_nexthop.h.
+
+2000-07-31  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgpd.c (bgp_show_summary): "show ip bgp summary" shows own BGP
+	identifier.  And status is changed like below.
+
+	State/Pref   -> State/PfxRcd
+	Shutdown     -> Idle (Admin)
+	PrefixOvflw  -> Idle (PfxCt)
+
+	* bgp_route.c (route_vty_out): Show internal route as "i".
+
+2000-07-13  Jim Bowen <jimb@zereau.net>
+
+	* bgp_snmp.c: Add BGP peer MIB implementation.
+
+2000-07-12  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgpd.c (bgp_show_peer): Fix typo.
+
+2000-07-11  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_routemap.c: Add commands for deleting set without argument.
+
+2000-07-03  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_zebra.c: Fix redistribute help strings.
+
+2000-07-01  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_show): When bgpd works as vtysh server send all
+	output to vty at once.
+
+2000-06-13  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_mplsvpn.c (no_vpnv4_network): "no network A.B.C.D/M rd WORD
+	tag WORD" command is added.
+
+	* bgp_ecommunity.c (ecommunity_vty_out): New function added.
+
+2000-06-12  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_show): Fix total number of prefix count bug.
+
+	* bgpd.c (bgp_show_peer): Display VPNv4 unicast configuration and
+	negotiation result in "show ip bgp neighbors".
+
+2000-06-12  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgpd.c: Fix help strings.
+	
+	* bgpd.h: Likewise.
+	
+2000-06-11  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_aggregate_unset): Fix bug of checking rn->info
+	instead of rn.  Reported by Akihiro Mizutani <mizutani@dml.com>.
+
+	* bgp_mplsvpn.c (vpnv4_network): For testing purpose, "network
+	A.B.C.D rd RD" is added to address-family vpnv4 unicast node.
+
+	* bgp_route.c (bgp_static_set): Set safi to p.safi.
+
+2000-06-10  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_show_prefix_list): Change to use bgp_show().
+	(bgp_show_regexp): Change to use bgp_show().
+	(show_adj_route): Change to display header.
+
+	* bgpd.c (clear_bgp): Set peer->v_start to default value when peer
+	is cleared manually.
+
+	* bgp_route.c (bgp_show_route): New function which display
+	specific BGP route.  Divided from bgp_show().
+	(bgp_static_delete): Delete all static route.
+
+2000-06-09  NOGUCHI Kay <kay@v6.access.co.jp>
+
+	* bgp_route.c (show_ipv6_bgp): "show ipv6 bgp" is broken with
+	invalid privious fix.  Now show_ipv6_bgp and show_ipv6_bgp_route
+	take care of "show ipv6 bgp [X:X::X:X]".  Same change for "show ip
+	mbgp" and "show ipv6 mbgp".
+
+2000-06-07  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_route.c: Fix help strings and command arguments.
+
+2000-06-06  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_ecommunity.c: Include prefix.h
+
+2000-06-05  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.h (struct bgp_info_tag): New structure to hold tag
+	value.
+
+	* bgp_route.c (bgp_adj_set): table NULL check is added.
+	(bgp_adj_unset): Likewise.
+	(bgp_adj_lookup): Likewise.
+	(bgp_adj_clear): Likewise.
+	(route_vty_out): Add SAFI check for nexthop display.
+	(bgp_withdraw): Add SAFI check for withdraw route.
+
+	* Remove all #ifdef MPLS_VPN then include it as default.
+
+	* bgpd.c: Temporary disable peer-group command until the
+	implementation is completed.
+
+	* bgp_routemap.c (bgp_route_map_init): Install
+	route_metric_match_cmd.
+	(route_match_metric_compile): MED value compile using strtoul.
+
+2000-06-05  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_filter.c: Fix help strings.  Change REGEXP to LINE.  Change
+	NAME to WORD.
+
+	* Change command argument to more comprehensive.
+
+	METRIC         -> <0-4294967295>
+	WEIGHT         -> <0-4294967295>
+	LOCAL_PREF     -> <0-4294967295>
+	IP_ADDR        -> A.B.C.D
+	AS             -> <1-65535>
+	AS-PATH-NAME   -> WORD
+	ACCESS_LIST    -> WORD
+	PREFIX_LIST    -> WORD
+	COMMUNITY      -> AA:NN
+	EXT_COMMUNITY  -> ASN:nn_or_IP-address:nn
+	IPv6_ADDR      -> X:X::X:X
+
+	* bgp_clist.c: Fix help strings.
+
+2000-06-03  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (peer_active): Add new function for check the peer is
+	active or not.
+	(neighbor_activate): New command "neighbor PEER activate" and "no
+	neighbor PEER activate" are added.
+
+	* bgp_packet.c: Include bgpd/bgp_mplsvpn.h.
+
+2000-06-02  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_clist.c: Fix commuity-list help strings.
+
+	* bgp_routemap.c: Fix "set community" help strings.  Add #define
+	SET_STR.  Use (unicast|multicast) argument for "set nlri" command.
+	
+2000-06-01  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_routemap.c (route_set_community_none_cmd): "set community
+	none" command is added to route-map.
+
+2000-06-01  Akihiro Mizutani <mizutani@dml.com>
+
+	* bgp_debug.c: Change "show debug" to "show debugging".  Now "show
+	debugging" is not used in VIEW_NODE.
+
+2000-05-30  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_fsm.c (bgp_timer_set): Add check for shutdown flag.  This
+	fix unconditional BGP connection.
+
+	* bgpd.c (peer_shutdown): Replace peer_shutdown() with
+	peer_change_flag_with_reset().
+
+2000-05-26  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (no_bgp_default_ipv4_unicast): Add "no bgp default
+	ipv4-unicast" command.
+
+	* bgpd.h (BGP_CONFIG_NO_DEFAULT_IPV4): Add new definition.
+
+	* bgp_filter.c (as_list_delete): Free all AS filter.
+
+	* bgp_clist.c (community_list_delete): Free all community entry.
+
+	* bgp_filter.c (no_ip_as_path_all): New DEFUN for "no ip as-path
+	access-list NAME".
+
+	* bgp_clist.c (no_ip_community_list_all): New DEFUN for "no ip
+	community-list NAME".
+
+2000-05-19  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (ipv6_mbgp_neighbor_routes): Change "show ip bgp PEER
+	routes" to "show ip bgp PEER received-routes"
+
+2000-05-14  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_ecommunity.c (ecommunity_parse): New file for Extended
+	Communities attribute.
+	* bgp_ecommunity.h: Likewise.
+
+2000-05-11  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_mplsvpn.h: New file for MPLS-VPN.
+	* bgp_mplsvpn.c: Likewise.
+
+	* bgpd.c (bgp_delete): Fix bug of "no router bgp" crush.
+
+2000-05-10  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (bgp_bestpath_missing_as_worst): Add "bgp bestpath
+	missing-as-worst".
+
+2000-05-08  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_routemap.c (match_community): Clarify help of "match
+	community".
+
+2000-05-02  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_aspath.c (aspath_cmp_left): Remove debug code.
+
+2000-04-27  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_info_cmp): Compare MED only both routes comes
+	from same neighboring AS.
+
+	* bgp_aspath.c (aspath_cmp_left): Compare leftmost AS value.
+
+	* bgp_route.c (bgp_info_cmp): Fix misused htonl() to ntohl().
+
+2000-04-26  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_output_filter): When distribute-list's
+	corresponding access-list does not exist, filter all routes.
+	(bgp_input_filter): Likewise.
+
+2000-04-19  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_attr.c (bgp_packet_attribute): Propagate MED to IBGP peer.
+
+	* bgp_route.c (bgp_info_cmp): Add evaluation of local preference.
+
+2000-04-18  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (bgp_distribute_update): Add struct access_list *
+	argument.
+
+2000-04-17  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_clist.c (community_list_dup_check): Add duplicate insertion
+	check.
+
+	* bgp_filter.c (as_list_dup_check): Add duplicate insertion check.
+
+	* bgp_route.c (bgp_show): Fix undeclared write variable.
+
+2000-04-13  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_routemap.c: Add "match ip address prefix-list".
+
+2000-03-29  Rick Payne <rickp@rossfell.co.uk>
+
+	* bgp_aspath.c (aspath_strip_confed): Fix realloc problem.
+
+2000-03-16  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_fsm.c (bgp_reconnect): Connect retry timer is expired when
+	the peer status is Connect.
+
+2000-03-03  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* Fix bug of rewritten originator-id.
+
+2000-01-27  Rick Payne <rickp@rossfell.co.uk>
+
+	* bgp_aspath.c (aspath_delimiter_char): New function.  Instead of
+	directly referencing array, search proper AS path delimiter.
+	(aspath_strip_confed): Strip the confederation stuff from the
+	front of an AS path.
+	(aspath_add_left_confed): New function for adding specified AS to
+	the leftmost AS_CONFED_SEQUENCE.
+
+	* bgp_aspath.h: Change AS_CONFED_SEQUENCE and AS_CONFED_SET value
+	to Cisco compatible.
+
+	* bgpd.c (bgp_confederation_id_set): Confederation configuration.
+	(bgp_confederation_id_unset): Likewise.
+	(bgp_confederation_peers_check): Likewise.
+	(bgp_confederation_peers_add): Likewise.
+	(bgp_confederation_peers_remove): Likewise.
+	(bgp_confederation_peers_set): Likewise.
+	(bgp_confederation_peers_unset): Likewise.
+	(bgp_confederation_peers_print): Likewise.
+	
+2000-01-16  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c: Introduce peer_change_flag_with_reset() fucntion.
+
+2000-01-17  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_open.c (bgp_open_option_parse): When there is no common
+	capability send Unsupported Capability error to the peer.
+
+2000-01-14  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_open.c (bgp_capability_mp): Fix bug of mis-negotiation about
+	IPv6 unicast.
+
+	* bgpd.c (bgp_init): Add "soft-reconfiguration inbound" command.
+	
+2000-01-12  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (neighbor_strict_capability): Add
+	"strict-capability-match" command.
+
+	* bgp_zebra.c (bgp_if_update): Ignore NET127 determining
+	router-id.
+
+	* bgpd.c (peer_override_capability): Add "override-capability"
+	command.
+
+1999-12-16  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_packet.c (bgp_write): Change status to Idle and set timer
+	after write failed.
+
+1999-12-14  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_zebra.c (bgp_zebra_announce): Add info->selected check.
+
+1999-12-12  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (nlri_unfeasible): nlri_unfeasible() is merged with
+	nlri_parse().
+
+1999-12-10  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_fsm.h (BGP_EVENT_DELETE): Macro added.
+
+	* bgp_fsm.c (bgp_stop): Clear all event threads of the peer when
+	the peer is cleared.
+
+	* bgp_zebra.c (bgp_nexthop_set): Clear interface index of
+	link-local address.  This is KAME specific problem.
+
+1999-12-06  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_attr.c (bgp_mp_reach_parse): Comment out previous code for a
+	while.  We don't completely detect the link is shared or not at
+	this moment.
+
+	* bgp_packet.c (bgp_notify_send): Make shortcut call of
+	bgp_write() and bgp_stop().
+
+	* bgp_attr.c (bgp_mp_reach_parse): Fix serious bug when getting
+	global and link-local address.
+
+1999-12-05  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (no_neighbor_port): New command added.
+	(peer_new): Set send_community.
+
+1999-12-04  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (show_ip_bgp_summary): Changed to use bgp_show_summary().
+	(show_ip_mbgp_summary): Likewise.
+	(show_ipv6_bgp_summary): Likewise.
+	(show_ipv6_mbgp_summary): Add new command.
+	(peer_free): Free peer->host.
+	(peer_lookup_by_su): Delete function.
+	(ipv6_bgp_neighbor): Changed to use peer_remote_as().
+	(sockunion_vty_out): Function deleted.
+	(vty_clear_bgp): Use afi instead of family.
+	Delete old list bgp_list.  Use struct newlist *bgplist.
+	(peer_lookup_by_host): Function deleted.
+
+1999-12-03  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.h (struct peer_group): New structure added.
+	(struct peer_conf): New structure added.
+	(struct	peer): Change all prefix_count to unsigned long.
+	
+	* bgpd.c: Reconstruct all of VTY commands reflect internal
+	structure change.
+	Use bgplist instead of bgp_list.
+	Use peerlist intstead of peer_list.
+
+	* bgp_attr.c (bgp_mp_reach_parse): If nlri_parse return -1, stop
+	parsing then return immediately.
+
+	* bgp_route.c (nlri_parse): When NLRI parse error occured, return
+	-1.
+	(nlri_process): Use pcount_v4_{unicast,multicast}.
+	(nlri_delete): Likewise.
+
+1999-11-25  Robert Olsson <Robert.Olsson@data.slu.se>
+
+	* bgp_routemap.c (route_match_nlri): `match nlri
+	unicast|multicast' and `set nlri unicast|multicast' command are
+	added.
+
+1999-11-22  Robert Olsson <Robert.Olsson@data.slu.se>
+
+	* bgpd.c: Add translate-update support.
+
+	* bgpd.h (TRANSLATE_UPDATE_OFF): Add translate-update definition.
+
+1999-11-19  Robert.Olsson@data.slu.se
+
+	* bgp_route.c (bgp_peer_delete): Add MBGP peer clear codes.
+
+1999-11-14  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_open.c (bgp_capability_mp): Temporary comment out
+	SAFI_UNICAST_MULTICAST handling until we know the meanings.
+
+1999-11-13  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_btoa.c: New file added.
+
+1999-11-12  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.h (struct peer): Add dont_capability flag.
+	(struct peer): Add override_capability flag.
+
+	* bgpd.c (neighbor_dont_capability_negotiation): `neighbor PEER
+	dont-capability-negotiation' added.
+
+1999-11-12  Bill Sommerfeld <sommerfeld@orchard.arlington.ma.us>
+
+	* bgp_attr.c (bgp_mp_reach_parse): Ignore link-local addresses
+	attribute from non-shared-network peers.
+
+1999-11-10  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_snmp.c: New file added.
+
+	* BGP4-MIB.txt: Updated to the latest Internet-Draft
+	draft-ietf-idr-bgp4-mib-04.txt.
+
+1999-11-09  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_route_init): Add `show ipv6 bgp prefix-list'.
+
+	* bgp_attr.c (bgp_mp_unreach_parse): Enclose safi setup with
+	#ifdef HAVE_MBGPV4.
+
+1999-11-08  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_dump.c (no_dump_bgp_all): Add [PATH] and [INTERVAL] to no
+	dump bgp commands.
+	(config_write_bgp_dump): Write interval value to the
+	configuration.
+
+1999-11-07  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_zebra.c: Redistribute route-map support is added.
+
+	* bgp_zebra.h: New file added.
+
+1999-11-04  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_dump.c: BGP packet dump routine compatible with MRT.
+	* bgp_dump.h: BGP packet dump routine compatible with MRT.
+
+	* bgp_debug.c: Renamed from bgp_dump.c
+	* bgp_debug.h: Renamed from bgp_dump.h
+
+1999-10-27  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* BGP4-MIB.txt: New file added.  Edited version of RFC1657.
+
+1999-10-25  Bill Sommerfeld <sommerfeld@orchard.arlington.ma.us>
+
+	* bgp_route.c (bgp_announce): If we're not on a shared network
+	with the peer and we don't have a link-local next hop, but the
+	inbound next-hop has a link-local address, don't readvertise it to
+	our peer.
+
+1999-10-25  Marc Boucher <marc@mbsi.ca>
+
+	* bgp_zebra.c: Add redistribute kernel command.
+
+1999-10-25  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_reset): New function added.
+
+	* bgpd.conf.sample2: Add IPv6 configuration sample.
+
+1999-10-24  Bill Sommerfeld <sommerfeld@orchard.arlington.ma.us>
+
+	* bgp_route.c (ipv6_aggregate_address): Function added.
+
+1999-10-21  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_packet.c (bgp_update): Unintern aspath, community, cluster
+	list after parsing BGP update packet.
+
+	* bgp_attr.c (bgp_attr_aspath): Intern parsed aspath.
+	(bgp_attr_community): Intern parsed community.
+	(bgp_attr_cluster_list): Intern parsed cluster list.
+
+	* bgp_routemap.c: Add `set community-additive' command.
+
+1999-10-21  Alexandr D. Kanevskiy <kad@blackcatlinux.com>
+
+	* bgp_routemap.c (route_set_local_pref): Fix bug of setting
+	attribute flag.
+
+1999-10-21  Bill Sommerfeld <sommerfeld@orchard.arlington.ma.us>
+
+	* bgp_route.c (bgp_announce): Add check of IPv6 default route
+	announcement.
+
+	* bgp_packet.c (bgp_update_send): Add BGP announcement logging.
+
+1999-10-15  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* `show ip[v6] bgp PREFIX' show uptime of the route.
+
+1999-10-04  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (bgp_filter_set): Delete PEER_FAMILY_{IPV4,IPV6}. instead
+	of that use AF_INET and AF_INET6 directly.
+	(vty_clear_bgp): Add new function to support various clear ip bgp
+	method.
+
+1999-10-04  Lars Fenneberg <lf@elemental.net>
+
+	* bgpd.c (clear_ip_bgp): Add `clear ip bgp ASN'.
+
+1999-10-03  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_routemap.c: Add `match ip prefix-list' and `match ipv6
+	prefix-list'.
+
+1999-09-28  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (bgp_collision_detect): Add BGP collision detection
+	function.
+
+1999-09-26  Blake Meike <bmeike@adero.com>
+
+	* bgpd.c (neighbor_port): New command `neighbor PEER port PORT' is
+	added.
+
+1999-08-24  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (no_neighbor_timers_keepalive): Change MIN to min.  Add
+	min() macro.
+
+1999-08-19  Rick Payne <rickp@rossfell.co.uk>
+
+	* bgp_packet.c (bgp_open): BGP holdtimer bug is fixed.  Make BGP
+	keepalive timer configurable.
+
+1999-08-15  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_zebra.c (bgp_redistribute_set): Fix redistribute bug.
+
+1999-08-13  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (bgp_peer_display): show ip bgp neighbors PEER only list
+	the peer not all of them.
+
+1999-08-11  Rick Payne <rickp@rossfell.co.uk>
+
+	* bgp_route.c (bgp_announce): Remove MED if its an EBGP peer -
+	will get overwritten by route-maps.
+
+1999-08-08  Rick Payne <rickp@rossfell.co.uk>
+
+	* bgp_routemap.c: Multi protocol route-map modification.
+
+1999-08-01  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c: Set network statement route's origin attribute as
+	igp.
+
+	* bgp_zebra.c: Set redistribute route's origin attribute as
+	incomplete.
+
+	* bgp_route.c (bgp_info_cmp): Add attribute existance check,
+	origin attribute check, BGP peer type check.
+
+1999-07-30  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_peer_delete): Reselect of IPv6 route.
+
+1999-07-29  Rick Payne <rickp@rossfell.co.uk>
+
+	* Changed route-maps to behave in a more cisco-like fashion
+
+1999-07-27  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_fsm.c (bgp_stop): Very serious bug of bgp_stop () is fixed.
+	When multiple route to the same destination exist, bgpd try to
+	announce the information to stopped peer.  Then add orphan write
+	thread is added.  This cause many strange behavior of bgpd.
+	Reported by Georg Hitsch <georg@atnet.at>.
+
+1999-07-23  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c: Change peer's A.B.C.D to PEER.
+
+1999-07-22  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_announce): Add hack for link-local nexthop.
+
+	* bgp_zebra.c (bgp_zebra_announce): Fill in nexthop address from
+	local address.
+
+1999-07-21  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_packet.c (bgp_open): Holdtime fetch bug is fixed.  Reported
+	by Yuji SEKIYA <sekiya@sfc.wide.ad.jp>.
+
+1999-07-15  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_fsm.c (fsm_holdtime): Don't close file descriptor in
+	fsm_holdtime ().
+
+1999-07-11  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_routemap.c: Add `set atomic-aggregate' command.
+
+1999-07-06  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_routemap.c (route_set_ip_nexthop_cmd): Change "ip nexthop"
+	to "ip next-hop".
+	
+1999-07-02  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (show_ipv6_bgp_regexp): `show ipv6 bgp regexp'
+	added.
+
+1999-07-01  Rick Payne <rickp@rossfell.co.uk>
+
+	* bgp_zebra.c (zebra_init): Install standard commands to
+	ZEBRA_NODE.
+
+1999-06-28  Rick Payne <rickp@rossfell.co.uk>
+
+	* bgpd.c (bgp_delete): bgp peer deletion bug is fixed.
+
+1999-06-25  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c: Add neighbor update-source command as ALIAS to
+	neighbor_interface.
+
+1999-06-19  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_attr.c (bgp_packet_attribute): Send community attribute when
+	send_community flag is set.
+
+	* bgpd.h (struct peer): Add send_community flag.
+
+1999-06-12  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (router_bgp): router bgp's argument changed from AS_NO to
+	<1-65535>.
+
+1999-06-08  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.h (struct bgp_info): Add subtype for BGP route type.
+
+1999-06-07  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_community.c (community_merge): Function added.
+
+1999-06-04  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_clist.c: New file.
+	* bgp_clist.h: New file.
+
+	* bgp_community.h (COMMUNITY_LOCAL_AS): Added for Cisco
+	compatibility.
+	(COMMUNITY_NO_ADVERTISE): Fix typo.
+
+1999-05-30  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_routemap.c: Add `set weight WEIGHT' command.
+
+	* bgpd.c: Remove all_digit_check function.  Instead of that use
+	all_digit function in lib/prefix.c.
+
+	* bgp_routemap.c (bgp_route_map_init): Install
+	no_set_ipv6_nexthop_global_cmd and no_set_ipv6_nexthop_local_cmd
+	element to the RMAP_NODE.
+
+1999-05-28  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_aspath.c (aspath_make_str): Declare aspath_delimiter_char
+	inside aspath_make_str function.
+	(aspath_prepend): New function is added for AS path prepend.
+	(aspath_make_str_count): Renamed from aspath_make_str.  AS path
+	count is set to the structure.
+	(aspath_merge): New function.
+
+1999-05-22  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_zebra.c (redistribute_bgp): Add new DEFUN.
+	(no_redistribute_bgp): Likewise.
+	(router_zebra): Semantics changed.  Now 'router zebra' is default
+	behavior of bgpd.
+
+1999-05-14  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_routemap.c: Add some commands to bgp route-map.
+	match ip next-hop: New command.
+	match metric: New command.
+	set metric: Doc fix.
+	set local-preference: Add DEFUN.
+
+1999-05-14  Stephen R. van den Berg <srb@cuci.nl>
+
+	* bgp_main.c (signal_init): SIGTERM call sigint.
+	(sigint): Loggging more better message.
+
+1999-05-12  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_attr.c (bgp_packet_attribute): AS path attribute extended
+	length bit check is added.
+
+1999-05-11  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_routemap.c (bgp_route_map_init): Call route_map_install_set
+	function with route_set_local_pref_cmd argument.
+	(no_match_aspath): Function added.
+	(route_set_metric): Set attribute flag bit.
+
+	* bgp_attr.c (bgp_packet_attribute): MULTI_EXIT_DISC is now in BGP
+	packet.
+
+1999-05-07  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (no_neighbor_timers_holdtime): `no neighbor PEER timers
+	holdtime' command is added.
+
+	* bgpd.h (BGP_DEFAULT_HOLDTIME_BIG): Delete define.
+
+	* bgpd.c (bgp_prefix_list_set): New function added.
+	(bgp_prefix_list_unset): Likewise.
+	(bgp_prefix_list_update): Likewise.
+	(show_ip_bgp_neighbors): prefix-list information display.
+
+1999-05-06  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (bgp_delete): Function added for `no router bgp'.
+
+1999-05-05  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_dump.c (bgp_dump_attr): Add originator_id display.
+
+	* bgpd.c (bgp_router_id): Even when address is malformed set the
+	value to configuration bug fixed.
+	(no_bgp_router_id): New function.
+	(no_bgp_cluster_id): New function.
+
+1999-05-04  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.h (BGP_ATTR_ORIGINATOR_ID): Changed from BGP_ATTR_ORIGINATOR.
+
+1999-05-02  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (bgp_announce): Add route reflector check.
+
+1999-05-01  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (bgp_cluster_id): Add function for route reflector.
+	(neighbor_route_reflector_client): Likewise.
+	(no_neighbor_route_reflector_client): Likewise.
+
+	* bgpd.h (struct bgp ): Add cluster for route reflector.
+
+	* bgp_route.c (show_ip_bgp_prefix_list): New command is added.
+
+1999-04-24  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* Makefile.am (noinst_HEADERS): Add bgp_filter.h
+
+	* bgp_aspath.c (aspath_undup): Function deleted.  aspath_free ()
+	has same functionality.
+
+	* bgp_filter.h: New file.
+
+	* bgp_aspath.c (aspath_unintern): Rename aspath_free () to
+	aspath_unintern ()
+	(aspath_free): New function.
+
+1999-04-23  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_aspath.c (aspath_aggregate): Function added.
+
+	* bgp_aspath.h (aspath_aggregate): Prototype added.
+
+	* bgp_aspath.c (aspath_empty_aspath): New argument
+	gated_dont_eat_flag is added.
+
+1999-04-18  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c: Add bgp_aggregate_ipv4 and bgp_aggregate_ipv6.
+
+1999-04-17  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c (aggregate_address): Function added.
+
+	* bgp_zebra.c (zebra_read): Change log to zlog.
+
+1999-04-15  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* Makefile.am (noninst_HEADERS): Added for make dist.
+
+1999-04-09  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* aspath_regex.c: Removed from distribution.
+
+1999-04-07  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_attr.c (bgp_packet_attribute): Old draft-00 packet treatment
+	bug fixed.
+
+1999-04-06  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_aspath.c (aspath_add_left): Fix empty aspath bug.  Reported
+	by kad@gibson.skif.net.
+
+	* bgp_regex.[ch]: New file added.
+
+	
+1999-04-05  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_filter.c: New file added.
+
+1999-04-01  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_aspath.c (aspath_empty_aspath): Change for peering with
+	gated.
+
+1999-03-24  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_main.c (main): Default loggin method changed from syslog to
+	stdout.
+
+1999-03-05  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c: Delete obsolete default attribute DEFUN.
+
+1999-03-04  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_attr.c: Make attribute structure put into attribute hash.
+
+1999-03-02  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_view.c : Delete file.
+
+1999-02-25  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_routemap.c (bgp_apply_route_map): Add prefix argument. 
+
+	* bgp_route.h (struct bgp_info): Add bgp_info structre.  I'll
+	replace bgp_route with this.
+
+	* bgp_routemap.c (route_match_ip_address): Fix bug of passing non
+	prefix value to access_list_apply(). 
+
+	* bgpd.conf.sample: Add route-map sample.
+	Delete obsolete default-attr statements.
+
+	* bgp_packet.c: Use stream_fifo for packet queueing.
+
+1999-02-24  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_aspath.c (aspath_add_left): add non empty aspath treatment.
+
+	* bgp_main.c: include unistd.h for daemon().
+
+	* bgp_route.c (nlri_process): add IPv6 table lookup.
+
+	* bgp_attr.c (route_parse_ipv6): call nlri_process().
+	(attr_make): Obsolete function attr_make deleted.
+
+1999-02-22  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_aspath.c (aspath_add_left): change function name from
+	aspath_add_leftmost_as().
+
+1999-02-21  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_aspath.c: add aspath_add_leftmost_as ().
+
+1999-02-18  Peter Galbavy  <Peter.Galbavy@knowledge.com>
+
+	* syslog support added
+
+1999-01-26  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c: DEFUN (neighbor_nexthop): deleted.
+	DEFUN (neighbor_distribute_list): added.
+
+1999-01-19  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.h (struct peer ): header_buf and read_buf is removed.
+
+	* bgp_peer.[ch]: Deleted.  Peer related functions are merged to
+	bgpd.c
+
+	* bgp_network.c: New file.
+	* bgp_network.h: New file.
+
+	* bgp_packet.h: New file.
+	
+1999-01-11  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_packet.c (bgp_keepalive_send): Now BGP keepalive packet is
+	buffered.
+
+1999-01-08  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_packet.c: New file.
+
+1998-12-22  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_zebra.c (zebra_client): Use zebra_connect() in lib/client.c. 
+
+	* `show ip bgp' bug fixed.
+	* aspath_log (): Remove argument logfp.
+
+1998-12-15  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_fsm.h: New file.
+
+1998-12-15  Magnus Ahltorp <map@stacken.kth.se>
+
+	* bgp_attr.c, bgp_community.h, bgp_dump.c, bgp_fsm.c, bgp_open.c
+	bgp_peer.c, bgp_peer.h, bgp_route.c, bgp_route.h, bgp_view.c
+	bgpd.c, bgpd.h, bgp_attr.c, bgp_community.h, bgp_dump.c,
+	bgp_fsm.c, bgp_open.c, bgp_peer.c, bgp_peer.h: Prototype fixes.
+
+1998-12-09  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (bgp_config_write): Delete vector v argument.
+
+1998-12-07  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.h: Delete annoying ld_[124]byte and st_[124]byte macros.
+
+1998-11-23  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_radix.[ch]: removed.
+
+1998-09-15  HEO SeonMeyong  <seirios@matrix.iri.co.jp>
+
+	* bgp_main.c: ifdef HYDRANGEA -> ifdef KAME
+
+1998-08-13  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_dump.c: delete nroute().
+
+1998-05-19  Yamshita TAKAO  <jargon@lares.dti.ne.jp>
+
+	* bgp_aspath.c: HAVE_CONFIG_H typo :-)
+	* bgpd.h: Modify for compile on Solaris.
+	* bgp_aspath.h: likewize
+	* bgp_community.h: likewize
+	* bgp_routemap.c: likewize
+
+1998-05-18  Yamshita TAKAO  <jargon@lares.dti.ne.jp>
+
+	* bgpd.h: Modify for compile on Solaris.
+	* bgp_aspath.h: likewize
+
+1998-05-08  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* routemap.[ch]: move to ../lib directory.
+
+1998-05-07  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* routemap.c (route_map_apply): add function.
+
+1998-05-06  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* routemap.h: add file.
+
+	* bgp_peer.h (enum ): change PEER_{IBGP,EBGP} to BGP_PEER_{IBGP,EBGP}
+
+1998-05-03  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* Makefile.am: sysconfdir_DATA added.
+
+1998-05-02  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_dump.c: add `debug bgp fsm'
+		      add `no debug bgp fsm'
+		      add `show debug bgp'
+	* bgp_open.c: File added.
+
+1998-05-01  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* .cvsignore: File added.
+
+1998-04-30  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_community.[ch]: File added.
+
+1998-03-04  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd now use lib/thread.[ch].
+
+1998-01-06  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.c (show_ip_bgp_neighbors): add 'show ip bgp neighbors' command.
+
+	* bgpd.h (BGP_DEFAULT_START_TIMER): change from 1 to 30.
+
+1997-12-30  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_vty.c: bgp_vty.c deleted.
+
+	* bgpd.c (config_write_neighbor): add ebgp-multihop command.
+
+1997-12-29  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_fsm.c: [-p bgp_port] and [-P vty_port] works
+
+1997-12-06  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_vty.c: new file.
+
+	* bgp_attr.c: add new logging system.
+
+1997-11-23  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* Change all inet_addr call into inet_aton.
+
+1997-11-10  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_radix.c: change radix_peer_delete
+
+1997-10-04  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_aspath.c: move AS_TOKEN_??? definition from header to c source.
+
+1997-09-12  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_dump.c (bgp_log_route): add dump_attr function
+
+1997-09-06  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_aspath.c (aspath_test): change AS_SET brace from '[' to '{'
+	* bgp_dump.c (bgp_log_route): change logfile format.
+
+1997-08-19  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_open.c (bgp_open): move bgp_open function from bgpd.c
+	* bgp_attr.c (community_str2com): add community value generation
+	* bgp_attr.h: add SAFI definition for BGP-4+
+
+1997-08-18  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgpd.h: add BGP_OPEN_OPT_CAP for Capabilities Optional Parameter
+	* Makefile.in: add bgp_open.o, delete bgp_loop.o
+	* bgp_open.c: newfile which manages BGP Open message
+	* bgp_loop.c: this file is merged with bgp_fsm.c
+	* bgp_radix.c (radix_add): radix_add() now return route_t instead
+	of int
+	(bgp_sim): now we can read update & withdraw from file
+	* bgp_route.c: add route_free() call into route_parse etc.
+
+1997-08-17  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_radix.c: Radix code is completely rewritten. It has better
+	memory treatment than old one.
+
+1997-08-14  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_route.c: route_alloc for route struct allocation statistics.
+	* bgpd.c (bgp_make_update): now we cann announce MED attribute.
+	* bgp_aspath.c (aspath_print_all): change aspath_print_all output
+	format.
+
+1997-08-13  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_term.c (term_parse): add command : show asstat, show ashash
+	* bgp_aspath.c: aspath_cmp bug fix
+	(aspath_print_all): add aspath_print_all ();
+	* bgp_peer.h: delete rlist element from struct peer.
+
+1997-08-12  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_aspath.c: completely rewritten.
+	* bgp_aspath.h: completely rewritten.
+	add AsPath, AsSegment structure
+	add AS_SET treatment
+	change Hash codes
+
+1997-08-09  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_attr.h: add Attribute flags defines
+	* bgp_route.c: delete rlist related functions
+	* bgp_aspath.c (as_origin): add as_origin function
+	(aspath_print): move from bgp_dump.c and add support of AS_SET
+	change Hash related function names.
+
+1997-08-08  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_aspath.h: add next entry, delete rlist entry from struct aspath
+
+1997-08-04  Kunihiro Ishiguro  <kunihiro@zebra.org>
+
+	* bgp_aspath.c (as_sort): add function as_sort
+	* bgp_aspath.h: add IBGP, EBGP
+
diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am
new file mode 100644
index 0000000..7f739f6
--- /dev/null
+++ b/bgpd/Makefile.am
@@ -0,0 +1,44 @@
+## Process this file with automake to produce Makefile.in.
+
+INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib
+DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
+INSTALL_SDATA=@INSTALL@ -m 600
+
+noinst_LIBRARIES = libbgp.a
+sbin_PROGRAMS = bgpd
+
+libbgp_a_SOURCES = \
+	bgpd.c bgp_fsm.c bgp_aspath.c bgp_community.c bgp_attr.c \
+	bgp_debug.c bgp_route.c bgp_zebra.c bgp_open.c bgp_routemap.c \
+	bgp_packet.c bgp_network.c bgp_filter.c bgp_regex.c bgp_clist.c \
+	bgp_dump.c bgp_snmp.c bgp_ecommunity.c bgp_mplsvpn.c bgp_nexthop.c \
+	bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c
+
+noinst_HEADERS = \
+	bgp_aspath.h bgp_attr.h bgp_community.h bgp_debug.h bgp_fsm.h \
+	bgp_network.h bgp_open.h bgp_packet.h bgp_regex.h bgp_route.h \
+	bgpd.h bgp_filter.h bgp_clist.h bgp_dump.h bgp_zebra.h \
+	bgp_ecommunity.h bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \
+	bgp_advertise.h bgp_snmp.h bgp_vty.h
+
+bgpd_SOURCES = \
+	bgp_main.c $(libbgp_a_SOURCES)
+
+bgpd_LDADD = ../lib/libzebra.a
+
+sysconf_DATA = bgpd.conf.sample bgpd.conf.sample2
+
+EXTRA_DIST = $(sysconf_DATA) BGP4-MIB.txt
+
+install-sysconfDATA: $(sysconf_DATA)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(sysconfdir)
+	@list='$(sysconf_DATA)'; for p in $$list; do \
+	  if test -f $(srcdir)/$$p; then \
+	    echo " $(INSTALL_SDATA) $(srcdir)/$$p $(DESTDIR)$(sysconfdir)/$$p"; \
+	    $(INSTALL_SDATA) $(srcdir)/$$p $(DESTDIR)$(sysconfdir)/$$p; \
+	  else if test -f $$p; then \
+	    echo " $(INSTALL_SDATA) $$p $(DESTDIR)$(sysconfdir)/$$p"; \
+	    $(INSTALL_SDATA) $$p $(DESTDIR)$(sysconfdir)/$$p; \
+	  fi; fi; \
+	done
diff --git a/bgpd/Makefile.in b/bgpd/Makefile.in
new file mode 100644
index 0000000..06c5189
--- /dev/null
+++ b/bgpd/Makefile.in
@@ -0,0 +1,534 @@
+# Makefile.in generated by automake 1.7 from Makefile.am.
+# @configure_input@
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_triplet = @host@
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BGPD = @BGPD@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CURSES = @CURSES@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+IF_METHOD = @IF_METHOD@
+IF_PROC = @IF_PROC@
+
+INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IPFORWARD = @IPFORWARD@
+KERNEL_METHOD = @KERNEL_METHOD@
+LDFLAGS = @LDFLAGS@
+LIBPAM = @LIBPAM@
+LIBS = @LIBS@
+LIB_IPV6 = @LIB_IPV6@
+LIB_REGEX = @LIB_REGEX@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MULTIPATH_NUM = @MULTIPATH_NUM@
+OBJEXT = @OBJEXT@
+OSPF6D = @OSPF6D@
+OSPFD = @OSPFD@
+OTHER_METHOD = @OTHER_METHOD@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+RIPD = @RIPD@
+RIPNGD = @RIPNGD@
+RTREAD_METHOD = @RTREAD_METHOD@
+RT_METHOD = @RT_METHOD@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+VTYSH = @VTYSH@
+ZEBRA = @ZEBRA@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__include = @am__include@
+am__quote = @am__quote@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+INSTALL_SDATA = @INSTALL@ -m 600
+
+noinst_LIBRARIES = libbgp.a
+sbin_PROGRAMS = bgpd
+
+libbgp_a_SOURCES = \
+	bgpd.c bgp_fsm.c bgp_aspath.c bgp_community.c bgp_attr.c \
+	bgp_debug.c bgp_route.c bgp_zebra.c bgp_open.c bgp_routemap.c \
+	bgp_packet.c bgp_network.c bgp_filter.c bgp_regex.c bgp_clist.c \
+	bgp_dump.c bgp_snmp.c bgp_ecommunity.c bgp_mplsvpn.c bgp_nexthop.c \
+	bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c
+
+
+noinst_HEADERS = \
+	bgp_aspath.h bgp_attr.h bgp_community.h bgp_debug.h bgp_fsm.h \
+	bgp_network.h bgp_open.h bgp_packet.h bgp_regex.h bgp_route.h \
+	bgpd.h bgp_filter.h bgp_clist.h bgp_dump.h bgp_zebra.h \
+	bgp_ecommunity.h bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \
+	bgp_advertise.h bgp_snmp.h bgp_vty.h
+
+
+bgpd_SOURCES = \
+	bgp_main.c $(libbgp_a_SOURCES)
+
+
+bgpd_LDADD = ../lib/libzebra.a
+
+sysconf_DATA = bgpd.conf.sample bgpd.conf.sample2
+
+EXTRA_DIST = $(sysconf_DATA) BGP4-MIB.txt
+subdir = bgpd
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+
+libbgp_a_AR = $(AR) cru
+libbgp_a_LIBADD =
+am_libbgp_a_OBJECTS = bgpd.$(OBJEXT) bgp_fsm.$(OBJEXT) \
+	bgp_aspath.$(OBJEXT) bgp_community.$(OBJEXT) bgp_attr.$(OBJEXT) \
+	bgp_debug.$(OBJEXT) bgp_route.$(OBJEXT) bgp_zebra.$(OBJEXT) \
+	bgp_open.$(OBJEXT) bgp_routemap.$(OBJEXT) bgp_packet.$(OBJEXT) \
+	bgp_network.$(OBJEXT) bgp_filter.$(OBJEXT) bgp_regex.$(OBJEXT) \
+	bgp_clist.$(OBJEXT) bgp_dump.$(OBJEXT) bgp_snmp.$(OBJEXT) \
+	bgp_ecommunity.$(OBJEXT) bgp_mplsvpn.$(OBJEXT) \
+	bgp_nexthop.$(OBJEXT) bgp_damp.$(OBJEXT) bgp_table.$(OBJEXT) \
+	bgp_advertise.$(OBJEXT) bgp_vty.$(OBJEXT)
+libbgp_a_OBJECTS = $(am_libbgp_a_OBJECTS)
+sbin_PROGRAMS = bgpd$(EXEEXT)
+PROGRAMS = $(sbin_PROGRAMS)
+
+am__objects_1 = bgpd.$(OBJEXT) bgp_fsm.$(OBJEXT) bgp_aspath.$(OBJEXT) \
+	bgp_community.$(OBJEXT) bgp_attr.$(OBJEXT) bgp_debug.$(OBJEXT) \
+	bgp_route.$(OBJEXT) bgp_zebra.$(OBJEXT) bgp_open.$(OBJEXT) \
+	bgp_routemap.$(OBJEXT) bgp_packet.$(OBJEXT) \
+	bgp_network.$(OBJEXT) bgp_filter.$(OBJEXT) bgp_regex.$(OBJEXT) \
+	bgp_clist.$(OBJEXT) bgp_dump.$(OBJEXT) bgp_snmp.$(OBJEXT) \
+	bgp_ecommunity.$(OBJEXT) bgp_mplsvpn.$(OBJEXT) \
+	bgp_nexthop.$(OBJEXT) bgp_damp.$(OBJEXT) bgp_table.$(OBJEXT) \
+	bgp_advertise.$(OBJEXT) bgp_vty.$(OBJEXT)
+am_bgpd_OBJECTS = bgp_main.$(OBJEXT) $(am__objects_1)
+bgpd_OBJECTS = $(am_bgpd_OBJECTS)
+bgpd_DEPENDENCIES = ../lib/libzebra.a
+bgpd_LDFLAGS =
+
+DEFAULT_INCLUDES =  -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/bgp_advertise.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/bgp_aspath.Po ./$(DEPDIR)/bgp_attr.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/bgp_clist.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/bgp_community.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/bgp_damp.Po ./$(DEPDIR)/bgp_debug.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/bgp_dump.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/bgp_ecommunity.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/bgp_filter.Po ./$(DEPDIR)/bgp_fsm.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/bgp_main.Po ./$(DEPDIR)/bgp_mplsvpn.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/bgp_network.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/bgp_nexthop.Po ./$(DEPDIR)/bgp_open.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/bgp_packet.Po ./$(DEPDIR)/bgp_regex.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/bgp_route.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/bgp_routemap.Po ./$(DEPDIR)/bgp_snmp.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/bgp_table.Po ./$(DEPDIR)/bgp_vty.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/bgp_zebra.Po ./$(DEPDIR)/bgpd.Po
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+DIST_SOURCES = $(libbgp_a_SOURCES) $(bgpd_SOURCES)
+DATA = $(sysconf_DATA)
+
+HEADERS = $(noinst_HEADERS)
+
+DIST_COMMON = $(noinst_HEADERS) ChangeLog Makefile.am Makefile.in
+SOURCES = $(libbgp_a_SOURCES) $(bgpd_SOURCES)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in:  Makefile.am  $(top_srcdir)/configure.in $(ACLOCAL_M4)
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  bgpd/Makefile
+Makefile:  $(srcdir)/Makefile.in  $(top_builddir)/config.status
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
+
+clean-noinstLIBRARIES:
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libbgp.a: $(libbgp_a_OBJECTS) $(libbgp_a_DEPENDENCIES) 
+	-rm -f libbgp.a
+	$(libbgp_a_AR) libbgp.a $(libbgp_a_OBJECTS) $(libbgp_a_LIBADD)
+	$(RANLIB) libbgp.a
+sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(sbindir)
+	@list='$(sbin_PROGRAMS)'; for p in $$list; do \
+	  p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+	  if test -f $$p \
+	  ; then \
+	    f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+	   echo " $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f"; \
+	   $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f || exit 1; \
+	  else :; fi; \
+	done
+
+uninstall-sbinPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(sbin_PROGRAMS)'; for p in $$list; do \
+	  f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+	  echo " rm -f $(DESTDIR)$(sbindir)/$$f"; \
+	  rm -f $(DESTDIR)$(sbindir)/$$f; \
+	done
+
+clean-sbinPROGRAMS:
+	-test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS)
+bgpd$(EXEEXT): $(bgpd_OBJECTS) $(bgpd_DEPENDENCIES) 
+	@rm -f bgpd$(EXEEXT)
+	$(LINK) $(bgpd_LDFLAGS) $(bgpd_OBJECTS) $(bgpd_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT) core *.core
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_advertise.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_aspath.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_attr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_clist.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_community.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_damp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_debug.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_dump.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_ecommunity.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_filter.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_fsm.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_mplsvpn.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_network.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_nexthop.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_open.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_packet.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_regex.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_route.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_routemap.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_snmp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_table.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_vty.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgp_zebra.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bgpd.Po@am__quote@
+
+distclean-depend:
+	-rm -rf ./$(DEPDIR)
+
+.c.o:
+@am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
+@am__fastdepCC_TRUE@	  -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \
+@am__fastdepCC_TRUE@	then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
+@am__fastdepCC_TRUE@	else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
+@am__fastdepCC_TRUE@	fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$<
+
+.c.obj:
+@am__fastdepCC_TRUE@	if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
+@am__fastdepCC_TRUE@	  -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'`; \
+@am__fastdepCC_TRUE@	then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
+@am__fastdepCC_TRUE@	else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
+@am__fastdepCC_TRUE@	fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'`
+uninstall-info-am:
+sysconfDATA_INSTALL = $(INSTALL_DATA)
+
+uninstall-sysconfDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(sysconf_DATA)'; for p in $$list; do \
+	  f="`echo $$p | sed -e 's|^.*/||'`"; \
+	  echo " rm -f $(DESTDIR)$(sysconfdir)/$$f"; \
+	  rm -f $(DESTDIR)$(sysconfdir)/$$f; \
+	done
+
+ETAGS = etags
+ETAGSFLAGS =
+
+CTAGS = ctags
+CTAGSFLAGS =
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(ETAGS_ARGS)$$tags$$unique" \
+	  || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	     $$tags $$unique
+
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkinstalldirs) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(DATA) $(HEADERS)
+
+installdirs:
+	$(mkinstalldirs) $(DESTDIR)$(sbindir) $(DESTDIR)$(sysconfdir)
+
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES clean-sbinPROGRAMS \
+	mostlyclean-am
+
+distclean: distclean-am
+
+distclean-am: clean-am distclean-compile distclean-depend \
+	distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-sbinPROGRAMS install-sysconfDATA
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-sbinPROGRAMS \
+	uninstall-sysconfDATA
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-noinstLIBRARIES clean-sbinPROGRAMS ctags distclean \
+	distclean-compile distclean-depend distclean-generic \
+	distclean-tags distdir dvi dvi-am info info-am install \
+	install-am install-data install-data-am install-exec \
+	install-exec-am install-info install-info-am install-man \
+	install-sbinPROGRAMS install-strip install-sysconfDATA \
+	installcheck installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+	uninstall-am uninstall-info-am uninstall-sbinPROGRAMS \
+	uninstall-sysconfDATA
+
+
+install-sysconfDATA: $(sysconf_DATA)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(sysconfdir)
+	@list='$(sysconf_DATA)'; for p in $$list; do \
+	  if test -f $(srcdir)/$$p; then \
+	    echo " $(INSTALL_SDATA) $(srcdir)/$$p $(DESTDIR)$(sysconfdir)/$$p"; \
+	    $(INSTALL_SDATA) $(srcdir)/$$p $(DESTDIR)$(sysconfdir)/$$p; \
+	  else if test -f $$p; then \
+	    echo " $(INSTALL_SDATA) $$p $(DESTDIR)$(sysconfdir)/$$p"; \
+	    $(INSTALL_SDATA) $$p $(DESTDIR)$(sysconfdir)/$$p; \
+	  fi; fi; \
+	done
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c
new file mode 100644
index 0000000..4778a97
--- /dev/null
+++ b/bgpd/bgp_advertise.c
@@ -0,0 +1,405 @@
+/* BGP advertisement and adjacency
+   Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "command.h"
+#include "memory.h"
+#include "prefix.h"
+#include "hash.h"
+#include "thread.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_table.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_advertise.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_aspath.h"
+#include "bgpd/bgp_packet.h"
+#include "bgpd/bgp_fsm.h"
+#include "bgpd/bgp_mplsvpn.h"
+
+/* BGP advertise attribute is used for pack same attribute update into
+   one packet.  To do that we maintain attribute hash in struct
+   peer.  */
+static struct bgp_advertise_attr *
+baa_new ()
+{
+  return (struct bgp_advertise_attr *)
+    XCALLOC (MTYPE_BGP_ADVERTISE_ATTR, sizeof (struct bgp_advertise_attr));
+}
+
+static void
+baa_free (struct bgp_advertise_attr *baa)
+{
+  XFREE (MTYPE_BGP_ADVERTISE_ATTR, baa);
+}
+
+static void *
+baa_hash_alloc (struct bgp_advertise_attr *ref)
+{
+  struct bgp_advertise_attr *baa;
+
+  baa = baa_new ();
+  baa->attr = ref->attr;
+  return baa;
+}
+
+static unsigned int
+baa_hash_key (struct bgp_advertise_attr *baa)
+{
+  return attrhash_key_make (baa->attr);
+}
+
+static int
+baa_hash_cmp (struct bgp_advertise_attr *baa1, struct bgp_advertise_attr *baa2)
+{
+  return attrhash_cmp (baa1->attr, baa2->attr);
+}
+
+/* BGP update and withdraw information is stored in BGP advertise
+   structure.  This structure is referred from BGP adjacency
+   information.  */
+static struct bgp_advertise *
+bgp_advertise_new ()
+{
+  return (struct bgp_advertise *) 
+    XCALLOC (MTYPE_BGP_ADVERTISE, sizeof (struct bgp_advertise));
+}
+
+void
+bgp_advertise_free (struct bgp_advertise *adv)
+{
+  XFREE (MTYPE_BGP_ADVERTISE, adv);
+}
+
+void
+bgp_advertise_add (struct bgp_advertise_attr *baa,
+		   struct bgp_advertise *adv)
+{
+  adv->next = baa->adv;
+  if (baa->adv)
+    baa->adv->prev = adv;
+  baa->adv = adv;
+}
+
+void
+bgp_advertise_delete (struct bgp_advertise_attr *baa,
+		      struct bgp_advertise *adv)
+{
+  if (adv->next)
+    adv->next->prev = adv->prev;
+  if (adv->prev)
+    adv->prev->next = adv->next;
+  else
+    baa->adv = adv->next;
+}
+
+static struct bgp_advertise_attr *
+bgp_advertise_intern (struct hash *hash, struct attr *attr)
+{
+  struct bgp_advertise_attr ref;
+  struct bgp_advertise_attr *baa;
+
+  ref.attr = bgp_attr_intern (attr);
+  baa = (struct bgp_advertise_attr *) hash_get (hash, &ref, baa_hash_alloc);
+  baa->refcnt++;
+
+  return baa;
+}
+
+void
+bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *baa)
+{
+  if (baa->refcnt)
+    baa->refcnt--;
+
+  if (baa->refcnt && baa->attr)
+    bgp_attr_unintern (baa->attr);
+  else
+    {
+      if (baa->attr)
+	{
+	  hash_release (hash, baa);
+	  bgp_attr_unintern (baa->attr);
+	}
+      baa_free (baa);
+    }
+}
+
+/* BGP adjacency keeps minimal advertisement information.  */
+void
+bgp_adj_out_free (struct bgp_adj_out *adj)
+{
+  XFREE (MTYPE_BGP_ADJ_OUT, adj);
+}
+
+int
+bgp_adj_out_lookup (struct peer *peer, struct prefix *p,
+		    afi_t afi, safi_t safi, struct bgp_node *rn)
+{
+  struct bgp_adj_out *adj;
+
+  for (adj = rn->adj_out; adj; adj = adj->next)
+    if (adj->peer == peer)
+      break;
+
+  if (! adj)
+    return 0;
+
+  return (adj->adv 
+	  ? (adj->adv->baa ? 1 : 0)
+	  : (adj->attr ? 1 : 0));
+}
+
+struct bgp_advertise *
+bgp_advertise_clean (struct peer *peer, struct bgp_adj_out *adj,
+		     afi_t afi, safi_t safi)
+{
+  struct bgp_advertise *adv;
+  struct bgp_advertise_attr *baa;
+  struct bgp_advertise *next;
+
+  adv = adj->adv;
+  baa = adv->baa;
+  next = NULL;
+
+  if (baa)
+    {
+      /* Unlink myself from advertise attribute FIFO.  */
+      bgp_advertise_delete (baa, adv);
+
+      /* Fetch next advertise candidate. */
+      next = baa->adv;
+
+      /* Unintern BGP advertise attribute.  */
+      bgp_advertise_unintern (peer->hash[afi][safi], baa);
+      adv->baa = NULL;
+      adv->rn = NULL;
+    }
+
+  /* Unlink myself from advertisement FIFO.  */
+  FIFO_DEL (adv);
+
+  /* Free memory.  */
+  bgp_advertise_free (adj->adv);
+  adj->adv = NULL;
+
+  return next;
+}
+
+void
+bgp_adj_out_set (struct bgp_node *rn, struct peer *peer, struct prefix *p,
+		 struct attr *attr, afi_t afi, safi_t safi,
+		 struct bgp_info *binfo)
+{
+  struct bgp_adj_out *adj = NULL;
+  struct bgp_advertise *adv;
+
+#ifdef DISABLE_BGP_ANNOUNCE
+  return;
+#endif /* DISABLE_BGP_ANNOUNCE */
+
+  /* Look for adjacency information. */
+  if (rn)
+    {
+      for (adj = rn->adj_out; adj; adj = adj->next)
+	if (adj->peer == peer)
+	  break;
+    }
+
+  if (! adj)
+    {
+      adj = XCALLOC (MTYPE_BGP_ADJ_OUT, sizeof (struct bgp_adj_out));
+
+      if (rn)
+        {
+          BGP_ADJ_OUT_ADD (rn, adj);
+          bgp_lock_node (rn);
+        }
+    }
+
+  if (adj->adv)
+    bgp_advertise_clean (peer, adj, afi, safi);
+
+  adj->peer = peer;
+  adj->adv = bgp_advertise_new ();
+
+  adv = adj->adv;
+  adv->rn = rn;
+  adv->binfo = binfo;
+  if (attr)
+    adv->baa = bgp_advertise_intern (peer->hash[afi][safi], attr);
+  else
+    adv->baa = baa_new ();
+  adv->adj = adj;
+
+  /* Add new advertisement to advertisement attribute list. */
+  bgp_advertise_add (adv->baa, adv);
+
+  FIFO_ADD (&peer->sync[afi][safi]->update, &adv->fifo);
+}
+
+void
+bgp_adj_out_unset (struct bgp_node *rn, struct peer *peer, struct prefix *p, 
+		   afi_t afi, safi_t safi)
+{
+  struct bgp_adj_out *adj;
+  struct bgp_advertise *adv;
+
+#ifdef DISABLE_BGP_ANNOUNCE
+  return;
+#endif /* DISABLE_BGP_ANNOUNCE */
+
+  /* Lookup existing adjacency, if it is not there return immediately.  */
+  for (adj = rn->adj_out; adj; adj = adj->next)
+    if (adj->peer == peer)
+      break;
+
+  if (! adj)
+    return;
+
+  /* Clearn up previous advertisement.  */
+  if (adj->adv)
+    bgp_advertise_clean (peer, adj, afi, safi);
+
+  if (adj->attr)
+    {
+      /* We need advertisement structure.  */
+      adj->adv = bgp_advertise_new ();
+      adv = adj->adv;
+      adv->rn = rn;
+      adv->adj = adj;
+
+      /* Add to synchronization entry for withdraw announcement.  */
+      FIFO_ADD (&peer->sync[afi][safi]->withdraw, &adv->fifo);
+
+      /* Schedule packet write. */
+      BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+    }
+  else
+    {
+      /* Remove myself from adjacency. */
+      BGP_ADJ_OUT_DEL (rn, adj);
+      
+      /* Free allocated information.  */
+      bgp_adj_out_free (adj);
+
+      bgp_unlock_node (rn);
+    }
+}
+
+void
+bgp_adj_out_remove (struct bgp_node *rn, struct bgp_adj_out *adj, 
+		    struct peer *peer, afi_t afi, safi_t safi)
+{
+  if (adj->attr)
+    bgp_attr_unintern (adj->attr);
+
+  if (adj->adv)
+    bgp_advertise_clean (peer, adj, afi, safi);
+
+  BGP_ADJ_OUT_DEL (rn, adj);
+  bgp_adj_out_free (adj);
+}
+
+void
+bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr)
+{
+  struct bgp_adj_in *adj;
+
+  for (adj = rn->adj_in; adj; adj = adj->next)
+    {
+      if (adj->peer == peer)
+	{
+	  if (adj->attr != attr)
+	    {
+	      bgp_attr_unintern (adj->attr);
+	      adj->attr = bgp_attr_intern (attr);
+	    }
+	  return;
+	}
+    }
+  adj = XCALLOC (MTYPE_BGP_ADJ_IN, sizeof (struct bgp_adj_in));
+  adj->peer = peer;
+  adj->attr = bgp_attr_intern (attr);
+  BGP_ADJ_IN_ADD (rn, adj);
+  bgp_lock_node (rn);
+}
+
+void
+bgp_adj_in_remove (struct bgp_node *rn, struct bgp_adj_in *bai)
+{
+  bgp_attr_unintern (bai->attr);
+  BGP_ADJ_IN_DEL (rn, bai);
+  XFREE (MTYPE_BGP_ADJ_IN, bai);
+}
+
+void
+bgp_adj_in_unset (struct bgp_node *rn, struct peer *peer)
+{
+  struct bgp_adj_in *adj;
+
+  for (adj = rn->adj_in; adj; adj = adj->next)
+    if (adj->peer == peer)
+      break;
+
+  if (! adj)
+    return;
+
+  bgp_adj_in_remove (rn, adj);
+  bgp_unlock_node (rn);
+}
+
+void
+bgp_sync_init (struct peer *peer)
+{
+  afi_t afi;
+  safi_t safi;
+  struct bgp_synchronize *sync;
+
+  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+      {
+	sync = XCALLOC (MTYPE_TMP, sizeof (struct bgp_synchronize));
+	FIFO_INIT (&sync->update);
+	FIFO_INIT (&sync->withdraw);
+	FIFO_INIT (&sync->withdraw_low);
+	peer->sync[afi][safi] = sync;
+	peer->hash[afi][safi] = hash_create (baa_hash_key, baa_hash_cmp);
+      }
+}
+
+void
+bgp_sync_delete (struct peer *peer)
+{
+  afi_t afi;
+  safi_t safi;
+
+  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+      {
+	if (peer->sync[afi][safi])
+	  XFREE (MTYPE_TMP, peer->sync[afi][safi]);
+	peer->sync[afi][safi] = NULL;
+
+	hash_free (peer->hash[afi][safi]);
+      }
+}
diff --git a/bgpd/bgp_advertise.h b/bgpd/bgp_advertise.h
new file mode 100644
index 0000000..e2ae010
--- /dev/null
+++ b/bgpd/bgp_advertise.h
@@ -0,0 +1,178 @@
+/* BGP advertisement and adjacency
+   Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+/* BGP advertise FIFO.  */
+struct bgp_advertise_fifo
+{
+  struct bgp_advertise *next;
+  struct bgp_advertise *prev;
+};
+
+/* BGP advertise attribute.  */
+struct bgp_advertise_attr
+{
+  /* Head of advertisement pointer. */
+  struct bgp_advertise *adv;
+
+  /* Reference counter.  */
+  unsigned long refcnt;
+
+  /* Attribute pointer to be announced.  */
+  struct attr *attr;
+};
+
+struct bgp_advertise
+{
+  /* FIFO for advertisement.  */
+  struct bgp_advertise_fifo fifo;
+
+  /* Link list for same attribute advertise.  */
+  struct bgp_advertise *next;
+  struct bgp_advertise *prev;
+
+  /* Prefix information.  */
+  struct bgp_node *rn;
+
+  /* Reference pointer.  */
+  struct bgp_adj_out *adj;
+
+  /* Advertisement attribute.  */
+  struct bgp_advertise_attr *baa;
+
+  /* BGP info.  */
+  struct bgp_info *binfo;
+};
+
+/* BGP adjacency out.  */
+struct bgp_adj_out
+{
+  /* Lined list pointer.  */
+  struct bgp_adj_out *next;
+  struct bgp_adj_out *prev;
+
+  /* Advertised peer.  */
+  struct peer *peer;
+
+  /* Advertised attribute.  */
+  struct attr *attr;
+
+  /* Advertisement information.  */
+  struct bgp_advertise *adv;
+};
+
+/* BGP adjacency in. */
+struct bgp_adj_in
+{
+  /* Linked list pointer.  */
+  struct bgp_adj_in *next;
+  struct bgp_adj_in *prev;
+
+  /* Received peer.  */
+  struct peer *peer;
+
+  /* Received attribute.  */
+  struct attr *attr;
+};
+
+/* BGP advertisement list.  */
+struct bgp_synchronize
+{
+  struct bgp_advertise_fifo update;
+  struct bgp_advertise_fifo withdraw;
+  struct bgp_advertise_fifo withdraw_low;
+};
+
+/* FIFO -- first in first out structure and macros.  */
+struct fifo
+{
+  struct fifo *next;
+  struct fifo *prev;
+};
+
+#define FIFO_INIT(F)                                  \
+  do {                                                \
+    struct fifo *Xfifo = (struct fifo *)(F);          \
+    Xfifo->next = Xfifo->prev = Xfifo;                \
+  } while (0)
+
+#define FIFO_ADD(F,N)                                 \
+  do {                                                \
+    struct fifo *Xfifo = (struct fifo *)(F);          \
+    struct fifo *Xnode = (struct fifo *)(N);          \
+    Xnode->next = Xfifo;                              \
+    Xnode->prev = Xfifo->prev;                        \
+    Xfifo->prev = Xfifo->prev->next = Xnode;          \
+  } while (0)
+
+#define FIFO_DEL(N)                                   \
+  do {                                                \
+    struct fifo *Xnode = (struct fifo *)(N);          \
+    Xnode->prev->next = Xnode->next;                  \
+    Xnode->next->prev = Xnode->prev;                  \
+  } while (0)
+
+#define FIFO_HEAD(F)                                  \
+  ((((struct fifo *)(F))->next == (struct fifo *)(F)) \
+  ? NULL : (F)->next)
+
+/* BGP adjacency linked list.  */
+#define BGP_INFO_ADD(N,A,TYPE)                        \
+  do {                                                \
+    (A)->prev = NULL;                                 \
+    (A)->next = (N)->TYPE;                            \
+    if ((N)->TYPE)                                    \
+      (N)->TYPE->prev = (A);                          \
+    (N)->TYPE = (A);                                  \
+  } while (0)
+
+#define BGP_INFO_DEL(N,A,TYPE)                        \
+  do {                                                \
+    if ((A)->next)                                    \
+      (A)->next->prev = (A)->prev;                    \
+    if ((A)->prev)                                    \
+      (A)->prev->next = (A)->next;                    \
+    else                                              \
+      (N)->TYPE = (A)->next;                          \
+  } while (0)
+
+#define BGP_ADJ_IN_ADD(N,A)    BGP_INFO_ADD(N,A,adj_in)
+#define BGP_ADJ_IN_DEL(N,A)    BGP_INFO_DEL(N,A,adj_in)
+#define BGP_ADJ_OUT_ADD(N,A)   BGP_INFO_ADD(N,A,adj_out)
+#define BGP_ADJ_OUT_DEL(N,A)   BGP_INFO_DEL(N,A,adj_out)
+
+/* Prototypes.  */
+void bgp_adj_out_set (struct bgp_node *, struct peer *, struct prefix *,
+		      struct attr *, afi_t, safi_t, struct bgp_info *);
+void bgp_adj_out_unset (struct bgp_node *, struct peer *, struct prefix *,
+			afi_t, safi_t);
+void bgp_adj_out_remove (struct bgp_node *, struct bgp_adj_out *, 
+			 struct peer *, afi_t, safi_t);
+int bgp_adj_out_lookup (struct peer *, struct prefix *, afi_t, safi_t,
+			struct bgp_node *);
+
+void bgp_adj_in_set (struct bgp_node *, struct peer *, struct attr *);
+void bgp_adj_in_unset (struct bgp_node *, struct peer *);
+void bgp_adj_in_remove (struct bgp_node *, struct bgp_adj_in *);
+
+struct bgp_advertise *
+bgp_advertise_clean (struct peer *, struct bgp_adj_out *, afi_t, safi_t);
+
+void bgp_sync_init (struct peer *);
+void bgp_sync_delete (struct peer *);
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
new file mode 100644
index 0000000..fc5efb1
--- /dev/null
+++ b/bgpd/bgp_aspath.c
@@ -0,0 +1,1186 @@
+/* AS path management routines.
+   Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "hash.h"
+#include "memory.h"
+#include "vector.h"
+#include "vty.h"
+#include "str.h"
+#include "log.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_aspath.h"
+
+/* Attr. Flags and Attr. Type Code. */
+#define AS_HEADER_SIZE        2	 
+
+/* Two octet is used for AS value. */
+#define AS_VALUE_SIZE         sizeof (as_t)
+
+/* AS segment octet length. */
+#define ASSEGMENT_LEN(X)  ((X)->length * AS_VALUE_SIZE + AS_HEADER_SIZE)
+
+/* To fetch and store as segment value. */
+struct assegment
+{
+  u_char type;
+  u_char length;
+  as_t asval[1];
+};
+
+/* Hash for aspath.  This is the top level structure of AS path. */
+struct hash *ashash;
+
+static struct aspath *
+aspath_new ()
+{
+  struct aspath *aspath;
+
+  aspath = XMALLOC (MTYPE_AS_PATH, sizeof (struct aspath));
+  memset (aspath, 0, sizeof (struct aspath));
+  return aspath;
+}
+
+/* Free AS path structure. */
+void
+aspath_free (struct aspath *aspath)
+{
+  if (!aspath)
+    return;
+  if (aspath->data)
+    XFREE (MTYPE_AS_SEG, aspath->data);
+  if (aspath->str)
+    XFREE (MTYPE_AS_STR, aspath->str);
+  XFREE (MTYPE_AS_PATH, aspath);
+}
+
+/* Unintern aspath from AS path bucket. */
+void
+aspath_unintern (struct aspath *aspath)
+{
+  struct aspath *ret;
+
+  if (aspath->refcnt)
+    aspath->refcnt--;
+
+  if (aspath->refcnt == 0)
+    {
+      /* This aspath must exist in aspath hash table. */
+      ret = hash_release (ashash, aspath);
+      assert (ret != NULL);
+      aspath_free (aspath);
+    }
+}
+
+/* Return the start or end delimiters for a particular Segment type */
+#define AS_SEG_START 0
+#define AS_SEG_END 1
+static char
+aspath_delimiter_char (u_char type, u_char which)
+{
+  int i;
+  struct
+  {
+    int type;
+    char start;
+    char end;
+  } aspath_delim_char [] =
+    {
+      { AS_SET,             '{', '}' },
+      { AS_SEQUENCE,        ' ', ' ' },
+      { AS_CONFED_SET,      '[', ']' },
+      { AS_CONFED_SEQUENCE, '(', ')' },
+      { 0 }
+    };
+
+  for (i = 0; aspath_delim_char[i].type != 0; i++)
+    {
+      if (aspath_delim_char[i].type == type)
+	{
+	  if (which == AS_SEG_START)
+	    return aspath_delim_char[i].start;
+	  else if (which == AS_SEG_END)
+	    return aspath_delim_char[i].end;
+	}
+    }
+  return ' ';
+}
+
+/* Convert aspath structure to string expression. */
+char *
+aspath_make_str_count (struct aspath *as)
+{
+  int space;
+  u_char type;
+  caddr_t pnt;
+  caddr_t end;
+  struct assegment *assegment;
+  int str_size = ASPATH_STR_DEFAULT_LEN;
+  int str_pnt;
+  u_char *str_buf;
+  int count = 0;
+
+  /* Empty aspath. */
+  if (as->length == 0)
+    {
+      str_buf = XMALLOC (MTYPE_AS_STR, 1);
+      str_buf[0] = '\0';
+      as->count = count;
+      return str_buf;
+    }
+
+  /* Set default value. */
+  space = 0;
+  type = AS_SEQUENCE;
+
+  /* Set initial pointer. */
+  pnt = as->data;
+  end = pnt + as->length;
+
+  str_buf = XMALLOC (MTYPE_AS_STR, str_size);
+  str_pnt = 0;
+
+  assegment = (struct assegment *) pnt;
+
+  while (pnt < end)
+    {
+      int i;
+      int estimate_len;
+
+      /* For fetch value. */
+      assegment = (struct assegment *) pnt;
+
+      /* Check AS type validity. */
+      if ((assegment->type != AS_SET) && 
+	  (assegment->type != AS_SEQUENCE) &&
+	  (assegment->type != AS_CONFED_SET) && 
+	  (assegment->type != AS_CONFED_SEQUENCE))
+	{
+	  XFREE (MTYPE_AS_STR, str_buf);
+	  return NULL;
+	}
+
+      /* Check AS length. */
+      if ((pnt + (assegment->length * AS_VALUE_SIZE) + AS_HEADER_SIZE) > end)
+	{
+	  XFREE (MTYPE_AS_STR, str_buf);
+	  return NULL;
+	}
+
+      /* Buffer length check. */
+      estimate_len = ((assegment->length * 6) + 4);
+      
+      /* String length check. */
+      while (str_pnt + estimate_len >= str_size)
+	{
+	  str_size *= 2;
+	  str_buf = XREALLOC (MTYPE_AS_STR, str_buf, str_size);
+	}
+
+      /* If assegment type is changed, print previous type's end
+         character. */
+      if (type != AS_SEQUENCE)
+	str_buf[str_pnt++] = aspath_delimiter_char (type, AS_SEG_END);
+      if (space)
+	str_buf[str_pnt++] = ' ';
+
+      if (assegment->type != AS_SEQUENCE)
+	str_buf[str_pnt++] = aspath_delimiter_char (assegment->type, AS_SEG_START);
+
+      space = 0;
+
+      /* Increment count - ignoring CONFED SETS/SEQUENCES */
+      if (assegment->type != AS_CONFED_SEQUENCE
+	  && assegment->type != AS_CONFED_SET)
+	{
+	  if (assegment->type == AS_SEQUENCE)
+	    count += assegment->length;
+	  else if (assegment->type == AS_SET)
+	    count++;
+	}
+
+      for (i = 0; i < assegment->length; i++)
+	{
+	  int len;
+
+	  if (space)
+	    {
+	      if (assegment->type == AS_SET
+		  || assegment->type == AS_CONFED_SET)
+		str_buf[str_pnt++] = ',';
+	      else
+		str_buf[str_pnt++] = ' ';
+	    }
+	  else
+	    space = 1;
+
+	  len = sprintf (str_buf + str_pnt, "%d", ntohs (assegment->asval[i]));
+	  str_pnt += len;
+	}
+
+      type = assegment->type;
+      pnt += (assegment->length * AS_VALUE_SIZE) + AS_HEADER_SIZE;
+    }
+
+  if (assegment->type != AS_SEQUENCE)
+    str_buf[str_pnt++] = aspath_delimiter_char (assegment->type, AS_SEG_END);
+
+  str_buf[str_pnt] = '\0';
+
+  as->count = count;
+
+  return str_buf;
+}
+
+/* Intern allocated AS path. */
+struct aspath *
+aspath_intern (struct aspath *aspath)
+{
+  struct aspath *find;
+  
+  /* Assert this AS path structure is not interned. */
+  assert (aspath->refcnt == 0);
+
+  /* Check AS path hash. */
+  find = hash_get (ashash, aspath, hash_alloc_intern);
+
+  if (find != aspath)
+      aspath_free (aspath);
+
+  find->refcnt++;
+
+  if (! find->str)
+    find->str = aspath_make_str_count (find);
+
+  return find;
+}
+
+/* Duplicate aspath structure.  Created same aspath structure but
+   reference count and AS path string is cleared. */
+struct aspath *
+aspath_dup (struct aspath *aspath)
+{
+  struct aspath *new;
+
+  new = XMALLOC (MTYPE_AS_PATH, sizeof (struct aspath));
+  memset (new, 0, sizeof (struct aspath));
+
+  new->length = aspath->length;
+
+  if (new->length)
+    {
+      new->data = XMALLOC (MTYPE_AS_SEG, aspath->length);
+      memcpy (new->data, aspath->data, aspath->length);
+    }
+  else
+    new->data = NULL;
+
+  /* new->str = aspath_make_str_count (aspath); */
+
+  return new;
+}
+
+void *
+aspath_hash_alloc (struct aspath *arg)
+{
+  struct aspath *aspath;
+
+  /* New aspath strucutre is needed. */
+  aspath = XMALLOC (MTYPE_AS_PATH, sizeof (struct aspath));
+  memset ((void *) aspath, 0, sizeof (struct aspath));
+  aspath->length = arg->length;
+
+  /* In case of IBGP connection aspath's length can be zero. */
+  if (arg->length)
+    {
+      aspath->data = XMALLOC (MTYPE_AS_SEG, arg->length);
+      memcpy (aspath->data, arg->data, arg->length);
+    }
+  else
+    aspath->data = NULL;
+
+  /* Make AS path string. */
+  aspath->str = aspath_make_str_count (aspath);
+
+  /* Malformed AS path value. */
+  if (! aspath->str)
+    {
+      aspath_free (aspath);
+      return NULL;
+    }
+
+  return aspath;
+}
+
+/* AS path parse function.  pnt is a pointer to byte stream and length
+   is length of byte stream.  If there is same AS path in the the AS
+   path hash then return it else make new AS path structure. */
+struct aspath *
+aspath_parse (caddr_t pnt, int length)
+{
+  struct aspath as;
+  struct aspath *find;
+
+  /* If length is odd it's malformed AS path. */
+  if (length % 2)
+    return NULL;
+
+  /* Looking up aspath hash entry. */
+  as.data = pnt;
+  as.length = length;
+
+  /* If already same aspath exist then return it. */
+  find = hash_get (ashash, &as, aspath_hash_alloc);
+  if (! find)
+    return NULL;
+  find->refcnt++;
+
+  return find;
+}
+
+#define min(A,B) ((A) < (B) ? (A) : (B))
+
+#define ASSEGMENT_SIZE(N)  (AS_HEADER_SIZE + ((N) * AS_VALUE_SIZE))
+
+struct aspath *
+aspath_aggregate_segment_copy (struct aspath *aspath, struct assegment *seg,
+			       int i)
+{
+  struct assegment *newseg;
+
+  if (! aspath->data)
+    {
+      aspath->data = XMALLOC (MTYPE_AS_SEG, ASSEGMENT_SIZE (i));
+      newseg = (struct assegment *) aspath->data;
+      aspath->length = ASSEGMENT_SIZE (i);
+    }
+  else
+    {
+      aspath->data = XREALLOC (MTYPE_AS_SEG, aspath->data,
+			       aspath->length + ASSEGMENT_SIZE (i));
+      newseg = (struct assegment *) (aspath->data + aspath->length);
+      aspath->length += ASSEGMENT_SIZE (i);
+    }
+
+  newseg->type = seg->type;
+  newseg->length = i;
+  memcpy (newseg->asval, seg->asval, (i * AS_VALUE_SIZE));
+
+  return aspath;
+}
+
+struct assegment *
+aspath_aggregate_as_set_add (struct aspath *aspath, struct assegment *asset,
+			     as_t as)
+{
+  int i;
+
+  /* If this is first AS set member, create new as-set segment. */
+  if (asset == NULL)
+    {
+      if (! aspath->data)
+	{
+	  aspath->data = XMALLOC (MTYPE_AS_SEG, ASSEGMENT_SIZE (1));
+	  asset = (struct assegment *) aspath->data;
+	  aspath->length = ASSEGMENT_SIZE (1);
+	}
+      else
+	{
+	  aspath->data = XREALLOC (MTYPE_AS_SEG, aspath->data,
+				   aspath->length + ASSEGMENT_SIZE (1));
+	  asset = (struct assegment *) (aspath->data + aspath->length);
+	  aspath->length += ASSEGMENT_SIZE (1);
+	}
+      asset->type = AS_SET;
+      asset->length = 1;
+      asset->asval[0] = as;
+    }
+  else
+    {
+      size_t offset;
+
+      /* Check this AS value already exists or not. */
+      for (i = 0; i < asset->length; i++)
+	if (asset->asval[i] == as)
+	  return asset;
+
+      offset = (caddr_t) asset - (caddr_t) aspath->data;
+      aspath->data = XREALLOC (MTYPE_AS_SEG, aspath->data,
+			       aspath->length + AS_VALUE_SIZE);
+
+      asset = (struct assegment *) (aspath->data + offset);
+      aspath->length += AS_VALUE_SIZE;
+      asset->asval[asset->length] = as;
+      asset->length++;
+    }
+
+  return asset;
+}
+
+/* Modify as1 using as2 for aggregation. */
+struct aspath *
+aspath_aggregate (struct aspath *as1, struct aspath *as2)
+{
+  int i;
+  int minlen;
+  int match;
+  int match1;
+  int match2;
+  caddr_t cp1;
+  caddr_t cp2;
+  caddr_t end1;
+  caddr_t end2;
+  struct assegment *seg1;
+  struct assegment *seg2;
+  struct aspath *aspath;
+  struct assegment *asset;
+
+  match = 0;
+  minlen = 0;
+  aspath = NULL;
+  asset = NULL;
+  cp1 = as1->data;
+  end1 = as1->data + as1->length;
+  cp2 = as2->data;
+  end2 = as2->data + as2->length;
+
+  seg1 = (struct assegment *) cp1;
+  seg2 = (struct assegment *) cp2;
+
+  /* First of all check common leading sequence. */
+  while ((cp1 < end1) && (cp2 < end2))
+    {
+      /* Check segment type. */
+      if (seg1->type != seg2->type)
+	break;
+
+      /* Minimum segment length. */
+      minlen = min (seg1->length, seg2->length);
+
+      for (match = 0; match < minlen; match++)
+	if (seg1->asval[match] != seg2->asval[match])
+	  break;
+
+      if (match)
+	{
+	  if (! aspath)
+	    aspath = aspath_new();
+	  aspath = aspath_aggregate_segment_copy (aspath, seg1, match);
+	}
+
+      if (match != minlen || match != seg1->length 
+	  || seg1->length != seg2->length)
+	break;
+
+      cp1 += ((seg1->length * AS_VALUE_SIZE) + AS_HEADER_SIZE);
+      cp2 += ((seg2->length * AS_VALUE_SIZE) + AS_HEADER_SIZE);
+
+      seg1 = (struct assegment *) cp1;
+      seg2 = (struct assegment *) cp2;
+    }
+
+  if (! aspath)
+    aspath = aspath_new();
+
+  /* Make as-set using rest of all information. */
+  match1 = match;
+  while (cp1 < end1)
+    {
+      seg1 = (struct assegment *) cp1;
+
+      for (i = match1; i < seg1->length; i++)
+	asset = aspath_aggregate_as_set_add (aspath, asset, seg1->asval[i]);
+
+      match1 = 0;
+      cp1 += ((seg1->length * AS_VALUE_SIZE) + AS_HEADER_SIZE);
+    }
+
+  match2 = match;
+  while (cp2 < end2)
+    {
+      seg2 = (struct assegment *) cp2;
+
+      for (i = match2; i < seg2->length; i++)
+	asset = aspath_aggregate_as_set_add (aspath, asset, seg2->asval[i]);
+
+      match2 = 0;
+      cp2 += ((seg2->length * AS_VALUE_SIZE) + AS_HEADER_SIZE);
+    }
+
+  return aspath;
+}
+
+/* When a BGP router receives an UPDATE with an MP_REACH_NLRI
+   attribute, check the leftmost AS number in the AS_PATH attribute is
+   or not the peer's AS number. */ 
+int
+aspath_firstas_check (struct aspath *aspath, as_t asno)
+{
+  caddr_t pnt;
+  struct assegment *assegment;
+
+  if (aspath == NULL)
+    return 0;
+
+  pnt = aspath->data;
+  assegment = (struct assegment *) pnt;
+
+  if (assegment
+      && assegment->type == AS_SEQUENCE
+      && assegment->asval[0] == htons (asno))
+    return 1;
+
+  return 0;
+}
+
+/* AS path loop check.  If aspath contains asno then return 1. */
+int
+aspath_loop_check (struct aspath *aspath, as_t asno)
+{
+  caddr_t pnt;
+  caddr_t end;
+  struct assegment *assegment;
+  int count = 0;
+
+  if (aspath == NULL)
+    return 0;
+
+  pnt = aspath->data;
+  end = aspath->data + aspath->length;
+
+  while (pnt < end)
+    {
+      int i;
+      assegment = (struct assegment *) pnt;
+      
+      for (i = 0; i < assegment->length; i++)
+	if (assegment->asval[i] == htons (asno))
+	  count++;
+
+      pnt += (assegment->length * AS_VALUE_SIZE) + AS_HEADER_SIZE;
+    }
+  return count;
+}
+
+/* When all of AS path is private AS return 1.  */
+int
+aspath_private_as_check (struct aspath *aspath)
+{
+  caddr_t pnt;
+  caddr_t end;
+  struct assegment *assegment;
+
+  if (aspath == NULL)
+    return 0;
+
+  if (aspath->length == 0)
+    return 0;
+
+  pnt = aspath->data;
+  end = aspath->data + aspath->length;
+
+  while (pnt < end)
+    {
+      int i;
+      assegment = (struct assegment *) pnt;
+      
+      for (i = 0; i < assegment->length; i++)
+	{
+	  if (ntohs (assegment->asval[i]) < BGP_PRIVATE_AS_MIN
+	      || ntohs (assegment->asval[i]) > BGP_PRIVATE_AS_MAX)
+	    return 0;
+	}
+      pnt += (assegment->length * AS_VALUE_SIZE) + AS_HEADER_SIZE;
+    }
+  return 1;
+}
+
+/* Merge as1 to as2.  as2 should be uninterned aspath. */
+struct aspath *
+aspath_merge (struct aspath *as1, struct aspath *as2)
+{
+  caddr_t data;
+
+  if (! as1 || ! as2)
+    return NULL;
+
+  data = XMALLOC (MTYPE_AS_SEG, as1->length + as2->length);
+  memcpy (data, as1->data, as1->length);
+  memcpy (data + as1->length, as2->data, as2->length);
+
+  XFREE (MTYPE_AS_SEG, as2->data);
+  as2->data = data;
+  as2->length += as1->length;
+  as2->count += as1->count;
+  return as2;
+}
+
+/* Prepend as1 to as2.  as2 should be uninterned aspath. */
+struct aspath *
+aspath_prepend (struct aspath *as1, struct aspath *as2)
+{
+  caddr_t pnt;
+  caddr_t end;
+  struct assegment *seg1 = NULL;
+  struct assegment *seg2 = NULL;
+
+  if (! as1 || ! as2)
+    return NULL;
+
+  seg2 = (struct assegment *) as2->data;
+
+  /* In case of as2 is empty AS. */
+  if (seg2 == NULL)
+    {
+      as2->length = as1->length;
+      as2->data = XMALLOC (MTYPE_AS_SEG, as1->length);
+      as2->count = as1->count;
+      memcpy (as2->data, as1->data, as1->length);
+      return as2;
+    }
+
+  /* assegment points last segment of as1. */
+  pnt = as1->data;
+  end = as1->data + as1->length;
+  while (pnt < end)
+    {
+      seg1 = (struct assegment *) pnt;
+      pnt += (seg1->length * AS_VALUE_SIZE) + AS_HEADER_SIZE;
+    }
+
+  /* In case of as1 is empty AS. */
+  if (seg1 == NULL)
+    return as2;
+
+  /* Compare last segment type of as1 and first segment type of as2. */
+  if (seg1->type != seg2->type)
+    return aspath_merge (as1, as2);
+
+  if (seg1->type == AS_SEQUENCE)
+    {
+      caddr_t newdata;
+      struct assegment *seg = NULL;
+      
+      newdata = XMALLOC (MTYPE_AS_SEG, 
+			 as1->length + as2->length - AS_HEADER_SIZE);
+      memcpy (newdata, as1->data, as1->length);
+      seg = (struct assegment *) (newdata + ((caddr_t)seg1 - as1->data));
+      seg->length += seg2->length;
+      memcpy (newdata + as1->length, as2->data + AS_HEADER_SIZE,
+	      as2->length - AS_HEADER_SIZE);
+
+      XFREE (MTYPE_AS_SEG, as2->data);
+      as2->data = newdata;
+      as2->length += (as1->length - AS_HEADER_SIZE);
+      as2->count += as1->count;
+
+      return as2;
+    }
+  else
+    {
+      /* AS_SET merge code is needed at here. */
+      return aspath_merge (as1, as2);
+    }
+
+  /* Not reached */
+}
+
+/* Add specified AS to the leftmost of aspath. */
+static struct aspath *
+aspath_add_one_as (struct aspath *aspath, as_t asno, u_char type)
+{
+  struct assegment *assegment;
+
+  assegment = (struct assegment *) aspath->data;
+
+  /* In case of empty aspath. */
+  if (assegment == NULL || assegment->length == 0)
+    {
+      aspath->length = AS_HEADER_SIZE + AS_VALUE_SIZE;
+
+      if (assegment)
+	aspath->data = XREALLOC (MTYPE_AS_SEG, aspath->data, aspath->length);
+      else
+	aspath->data = XMALLOC (MTYPE_AS_SEG, aspath->length);
+
+      assegment = (struct assegment *) aspath->data;
+      assegment->type = type;
+      assegment->length = 1;
+      assegment->asval[0] = htons (asno);
+
+      return aspath;
+    }
+
+  if (assegment->type == type)
+    {
+      caddr_t newdata;
+      struct assegment *newsegment;
+
+      newdata = XMALLOC (MTYPE_AS_SEG, aspath->length + AS_VALUE_SIZE);
+      newsegment = (struct assegment *) newdata;
+
+      newsegment->type = type;
+      newsegment->length = assegment->length + 1;
+      newsegment->asval[0] = htons (asno);
+
+      memcpy (newdata + AS_HEADER_SIZE + AS_VALUE_SIZE,
+	      aspath->data + AS_HEADER_SIZE, 
+	      aspath->length - AS_HEADER_SIZE);
+
+      XFREE (MTYPE_AS_SEG, aspath->data);
+
+      aspath->data = newdata;
+      aspath->length += AS_VALUE_SIZE;
+    } else {
+      caddr_t newdata;
+      struct assegment *newsegment;
+
+      newdata = XMALLOC (MTYPE_AS_SEG, aspath->length + AS_VALUE_SIZE + AS_HEADER_SIZE);
+      newsegment = (struct assegment *) newdata;
+
+      newsegment->type = type;
+      newsegment->length = 1;
+      newsegment->asval[0] = htons (asno);
+
+      memcpy (newdata + AS_HEADER_SIZE + AS_VALUE_SIZE,
+	      aspath->data,
+	      aspath->length);
+
+      XFREE (MTYPE_AS_SEG, aspath->data);
+
+      aspath->data = newdata;
+      aspath->length += AS_HEADER_SIZE + AS_VALUE_SIZE;
+    }
+
+  return aspath;
+}
+
+/* Add specified AS to the leftmost of aspath. */
+struct aspath *
+aspath_add_seq (struct aspath *aspath, as_t asno)
+{
+  return aspath_add_one_as (aspath, asno, AS_SEQUENCE);
+}
+
+/* Compare leftmost AS value for MED check.  If as1's leftmost AS and
+   as2's leftmost AS is same return 1. */
+int
+aspath_cmp_left (struct aspath *aspath1, struct aspath *aspath2)
+{
+  struct assegment *seg1;
+  struct assegment *seg2;
+  as_t as1;
+  as_t as2;
+
+  seg1 = (struct assegment *) aspath1->data;
+  seg2 = (struct assegment *) aspath2->data;
+
+  while (seg1 && seg1->length 
+	 && (seg1->type == AS_CONFED_SEQUENCE || seg1->type == AS_CONFED_SET))
+    seg1 = (struct assegment *) ((caddr_t) seg1 + ASSEGMENT_LEN (seg1));
+  while (seg2 && seg2->length 
+	 && (seg2->type == AS_CONFED_SEQUENCE || seg2->type == AS_CONFED_SET))
+    seg2 = (struct assegment *) ((caddr_t) seg2 + ASSEGMENT_LEN (seg2));
+
+  /* Check as1's */
+  if (seg1 == NULL || seg1->length == 0 || seg1->type != AS_SEQUENCE)
+    return 0;
+  as1 = seg1->asval[0];
+
+  if (seg2 == NULL || seg2->length == 0 || seg2->type != AS_SEQUENCE)
+    return 0;
+  as2 = seg2->asval[0];
+
+  if (as1 == as2)
+    return 1;
+
+  return 0;
+}
+
+/* Compare leftmost AS value for MED check.  If as1's leftmost AS and
+   as2's leftmost AS is same return 1. (confederation as-path
+   only).  */
+int
+aspath_cmp_left_confed (struct aspath *aspath1, struct aspath *aspath2)
+{
+  struct assegment *seg1;
+  struct assegment *seg2;
+
+  as_t as1;
+  as_t as2;
+
+  if (aspath1->count || aspath2->count) 
+    return 0;
+
+  seg1 = (struct assegment *) aspath1->data;
+  seg2 = (struct assegment *) aspath2->data;
+
+  /* Check as1's */
+  if (seg1 == NULL || seg1->length == 0 || seg1->type != AS_CONFED_SEQUENCE)
+    return 0;
+  as1 = seg1->asval[0];
+
+  /* Check as2's */
+  if (seg2 == NULL || seg2->length == 0 || seg2->type != AS_CONFED_SEQUENCE)
+    return 0;
+  as2 = seg2->asval[0];
+
+  if (as1 == as2)
+    return 1;
+
+  return 0;
+}
+
+/* Delete first sequential AS_CONFED_SEQUENCE from aspath.  */
+struct aspath *
+aspath_delete_confed_seq (struct aspath *aspath)
+{
+  int seglen;
+  struct assegment *assegment;
+
+  if (! aspath)
+    return aspath;
+
+  assegment = (struct assegment *) aspath->data;
+
+  while (assegment)
+    {
+      if (assegment->type != AS_CONFED_SEQUENCE)
+	return aspath;
+
+      seglen = ASSEGMENT_LEN (assegment);
+
+      if (seglen == aspath->length)
+	{
+	  XFREE (MTYPE_AS_SEG, aspath->data);
+	  aspath->data = NULL;
+	  aspath->length = 0;
+	}
+      else
+	{
+	  memcpy (aspath->data, aspath->data + seglen,
+		  aspath->length - seglen);
+	  aspath->data = XREALLOC (MTYPE_AS_SEG, aspath->data,
+				   aspath->length - seglen);
+	  aspath->length -= seglen;
+	}
+
+      assegment = (struct assegment *) aspath->data;
+    }
+  return aspath;
+}
+
+/* Add new AS number to the leftmost part of the aspath as
+   AS_CONFED_SEQUENCE.  */
+struct aspath*
+aspath_add_confed_seq (struct aspath *aspath, as_t asno)
+{
+  return aspath_add_one_as (aspath, asno, AS_CONFED_SEQUENCE);
+}
+
+/* Add new as value to as path structure. */
+void
+aspath_as_add (struct aspath *as, as_t asno)
+{
+  caddr_t pnt;
+  caddr_t end;
+  struct assegment *assegment;
+
+  /* Increase as->data for new as value. */
+  as->data = XREALLOC (MTYPE_AS_SEG, as->data, as->length + 2);
+  as->length += 2;
+
+  pnt = as->data;
+  end = as->data + as->length;
+  assegment = (struct assegment *) pnt;
+
+  /* Last segment search procedure. */
+  while (pnt + 2 < end)
+    {
+      assegment = (struct assegment *) pnt;
+
+      /* We add 2 for segment_type and segment_length and segment
+         value assegment->length * 2. */
+      pnt += (AS_HEADER_SIZE + (assegment->length * AS_VALUE_SIZE));
+    }
+
+  assegment->asval[assegment->length] = htons (asno);
+  assegment->length++;
+}
+
+/* Add new as segment to the as path. */
+void
+aspath_segment_add (struct aspath *as, int type)
+{
+  struct assegment *assegment;
+
+  if (as->data == NULL)
+    {
+      as->data = XMALLOC (MTYPE_AS_SEG, 2);
+      assegment = (struct assegment *) as->data;
+      as->length = 2;
+    }
+  else
+    {
+      as->data = XREALLOC (MTYPE_AS_SEG, as->data, as->length + 2);
+      assegment = (struct assegment *) (as->data + as->length);
+      as->length += 2;
+    }
+
+  assegment->type = type;
+  assegment->length = 0;
+}
+
+struct aspath *
+aspath_empty ()
+{
+  return aspath_parse (NULL, 0);
+}
+
+struct aspath *
+aspath_empty_get ()
+{
+  struct aspath *aspath;
+
+  aspath = aspath_new ();
+  aspath->str = aspath_make_str_count (aspath);
+  return aspath;
+}
+
+unsigned long
+aspath_count ()
+{
+  return ashash->count;
+}     
+
+/* 
+   Theoretically, one as path can have:
+
+   One BGP packet size should be less than 4096.
+   One BGP attribute size should be less than 4096 - BGP header size.
+   One BGP aspath size should be less than 4096 - BGP header size -
+       BGP mandantry attribute size.
+*/
+
+/* AS path string lexical token enum. */
+enum as_token
+{
+  as_token_asval,
+  as_token_set_start,
+  as_token_set_end,
+  as_token_confed_start,
+  as_token_confed_end,
+  as_token_unknown
+};
+
+/* Return next token and point for string parse. */
+char *
+aspath_gettoken (char *buf, enum as_token *token, u_short *asno)
+{
+  char *p = buf;
+
+  /* Skip space. */
+  while (isspace ((int) *p))
+    p++;
+
+  /* Check the end of the string and type specify characters
+     (e.g. {}()). */
+  switch (*p)
+    {
+    case '\0':
+      return NULL;
+      break;
+    case '{':
+      *token = as_token_set_start;
+      p++;
+      return p;
+      break;
+    case '}':
+      *token = as_token_set_end;
+      p++;
+      return p;
+      break;
+    case '(':
+      *token = as_token_confed_start;
+      p++;
+      return p;
+      break;
+    case ')':
+      *token = as_token_confed_end;
+      p++;
+      return p;
+      break;
+    }
+
+  /* Check actual AS value. */
+  if (isdigit ((int) *p)) 
+    {
+      u_short asval;
+
+      *token = as_token_asval;
+      asval = (*p - '0');
+      p++;
+      while (isdigit ((int) *p)) 
+	{
+	  asval *= 10;
+	  asval += (*p - '0');
+	  p++;
+	}
+      *asno = asval;
+      return p;
+    }
+  
+  /* There is no match then return unknown token. */
+  *token = as_token_unknown;
+  return  p++;
+}
+
+struct aspath *
+aspath_str2aspath (char *str)
+{
+  enum as_token token;
+  u_short as_type;
+  u_short asno;
+  struct aspath *aspath;
+  int needtype;
+
+  aspath = aspath_new ();
+
+  /* We start default type as AS_SEQUENCE. */
+  as_type = AS_SEQUENCE;
+  needtype = 1;
+
+  while ((str = aspath_gettoken (str, &token, &asno)) != NULL)
+    {
+      switch (token)
+	{
+	case as_token_asval:
+	  if (needtype)
+	    {
+	      aspath_segment_add (aspath, as_type);
+	      needtype = 0;
+	    }
+	  aspath_as_add (aspath, asno);
+	  break;
+	case as_token_set_start:
+	  as_type = AS_SET;
+	  aspath_segment_add (aspath, as_type);
+	  needtype = 0;
+	  break;
+	case as_token_set_end:
+	  as_type = AS_SEQUENCE;
+	  needtype = 1;
+	  break;
+	case as_token_confed_start:
+	  as_type = AS_CONFED_SEQUENCE;
+	  aspath_segment_add (aspath, as_type);
+	  needtype = 0;
+	  break;
+	case as_token_confed_end:
+	  as_type = AS_SEQUENCE;
+	  needtype = 1;
+	  break;
+	case as_token_unknown:
+	default:
+	  return NULL;
+	  break;
+	}
+    }
+
+  aspath->str = aspath_make_str_count (aspath);
+
+  return aspath;
+}
+
+/* Make hash value by raw aspath data. */
+unsigned int
+aspath_key_make (struct aspath *aspath)
+{
+  unsigned int key = 0;
+  int length;
+  unsigned short *pnt;
+
+  length = aspath->length / 2;
+  pnt = (unsigned short *) aspath->data;
+
+  while (length)
+    {
+      key += *pnt++;
+      length--;
+    }
+
+  return key;
+}
+
+/* If two aspath have same value then return 1 else return 0 */
+int
+aspath_cmp (struct aspath *as1, struct aspath *as2)
+{
+  if (as1->length == as2->length 
+      && !memcmp (as1->data, as2->data, as1->length))
+    return 1;
+  else
+    return 0;
+}
+
+/* AS path hash initialize. */
+void
+aspath_init ()
+{
+  ashash = hash_create_size (32767, aspath_key_make, aspath_cmp);
+}
+
+/* return and as path value */
+const char *
+aspath_print (struct aspath *as)
+{
+  return as->str;
+}
+
+/* Printing functions */
+void
+aspath_print_vty (struct vty *vty, struct aspath *as)
+{
+  vty_out (vty, "%s", as->str);
+}
+
+void
+aspath_show_all_iterator (struct hash_backet *backet, struct vty *vty)
+{
+  struct aspath *as;
+
+  as = (struct aspath *) backet->data;
+
+  vty_out (vty, "[%p:%d] (%ld) ", backet, backet->key, as->refcnt);
+  vty_out (vty, "%s%s", as->str, VTY_NEWLINE);
+}
+
+/* Print all aspath and hash information.  This function is used from
+   `show ip bgp paths' command. */
+void
+aspath_print_all_vty (struct vty *vty)
+{
+  hash_iterate (ashash, 
+		(void (*) (struct hash_backet *, void *))
+		aspath_show_all_iterator,
+		vty);
+}
diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h
new file mode 100644
index 0000000..0295faf
--- /dev/null
+++ b/bgpd/bgp_aspath.h
@@ -0,0 +1,77 @@
+/* AS path related definitions.
+   Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+/* AS path segment type.  */
+#define AS_SET                       1
+#define AS_SEQUENCE                  2
+#define AS_CONFED_SEQUENCE           3
+#define AS_CONFED_SET                4
+
+/* Private AS range defined in RFC2270.  */
+#define BGP_PRIVATE_AS_MIN       64512
+#define BGP_PRIVATE_AS_MAX       65535
+
+/* AS path may be include some AsSegments.  */
+struct aspath 
+{
+  /* Reference count to this aspath.  */
+  unsigned long refcnt;
+
+  /* Rawdata length.  */
+  int length;
+
+  /* AS count.  */
+  int count;
+
+  /* Rawdata.  */
+  caddr_t data;
+
+  /* String expression of AS path.  This string is used by vty output
+     and AS path regular expression match.  */
+  char *str;
+};
+
+#define ASPATH_STR_DEFAULT_LEN 32
+
+/* Prototypes. */
+void aspath_init ();
+struct aspath *aspath_parse ();
+struct aspath *aspath_dup (struct aspath *);
+struct aspath *aspath_aggregate (struct aspath *, struct aspath *);
+struct aspath *aspath_prepend (struct aspath *, struct aspath *);
+struct aspath *aspath_add_seq (struct aspath *, as_t);
+struct aspath *aspath_add_confed_seq (struct aspath *, as_t);
+int aspath_cmp_left (struct aspath *, struct aspath *);
+int aspath_cmp_left_confed (struct aspath *, struct aspath *);
+struct aspath *aspath_delete_confed_seq (struct aspath *);
+struct aspath *aspath_empty ();
+struct aspath *aspath_empty_get ();
+struct aspath *aspath_str2aspath (char *);
+void aspath_free (struct aspath *);
+struct aspath *aspath_intern (struct aspath *);
+void aspath_unintern (struct aspath *);
+const char *aspath_print (struct aspath *);
+void aspath_print_vty (struct vty *, struct aspath *);
+void aspath_print_all_vty (struct vty *);
+unsigned int aspath_key_make (struct aspath *);
+int aspath_loop_check (struct aspath *, as_t);
+int aspath_private_as_check (struct aspath *);
+int aspath_firstas_check (struct aspath *, as_t);
+unsigned long aspath_count ();
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
new file mode 100644
index 0000000..480bb91
--- /dev/null
+++ b/bgpd/bgp_attr.c
@@ -0,0 +1,1838 @@
+/* BGP attributes management routines.
+   Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "linklist.h"
+#include "prefix.h"
+#include "memory.h"
+#include "vector.h"
+#include "vty.h"
+#include "stream.h"
+#include "log.h"
+#include "hash.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_aspath.h"
+#include "bgpd/bgp_community.h"
+#include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_packet.h"
+#include "bgpd/bgp_ecommunity.h"
+
+/* Attribute strings for logging. */
+struct message attr_str [] = 
+{
+  { BGP_ATTR_ORIGIN,           "ORIGIN" }, 
+  { BGP_ATTR_AS_PATH,          "AS_PATH" }, 
+  { BGP_ATTR_NEXT_HOP,         "NEXT_HOP" }, 
+  { BGP_ATTR_MULTI_EXIT_DISC,  "MULTI_EXIT_DISC" }, 
+  { BGP_ATTR_LOCAL_PREF,       "LOCAL_PREF" }, 
+  { BGP_ATTR_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" }, 
+  { BGP_ATTR_AGGREGATOR,       "AGGREGATOR" }, 
+  { BGP_ATTR_COMMUNITIES,      "COMMUNITY" }, 
+  { BGP_ATTR_ORIGINATOR_ID,    "ORIGINATOR_ID" },
+  { BGP_ATTR_CLUSTER_LIST,     "CLUSTERLIST" }, 
+  { BGP_ATTR_DPA,              "DPA" },
+  { BGP_ATTR_ADVERTISER,       "ADVERTISER"} ,
+  { BGP_ATTR_RCID_PATH,        "RCID_PATH" },
+  { BGP_ATTR_MP_REACH_NLRI,    "MP_REACH_NLRI" },
+  { BGP_ATTR_MP_UNREACH_NLRI,  "MP_UNREACH_NLRI" },
+  { 0, NULL }
+};
+
+struct hash *cluster_hash;
+
+void *
+cluster_hash_alloc (struct cluster_list *val)
+{
+  struct cluster_list *cluster;
+
+  cluster = XMALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
+  cluster->length = val->length;
+
+  if (cluster->length)
+    {
+      cluster->list = XMALLOC (MTYPE_CLUSTER_VAL, val->length);
+      memcpy (cluster->list, val->list, val->length);
+    }
+  else
+    cluster->list = NULL;
+
+  cluster->refcnt = 0;
+
+  return cluster;
+}
+
+/* Cluster list related functions. */
+struct cluster_list *
+cluster_parse (caddr_t pnt, int length)
+{
+  struct cluster_list tmp;
+  struct cluster_list *cluster;
+
+  tmp.length = length;
+  tmp.list = (struct in_addr *) pnt;
+
+  cluster = hash_get (cluster_hash, &tmp, cluster_hash_alloc);
+  cluster->refcnt++;
+  return cluster;
+}
+
+int
+cluster_loop_check (struct cluster_list *cluster, struct in_addr originator)
+{
+  int i;
+    
+  for (i = 0; i < cluster->length / 4; i++)
+    if (cluster->list[i].s_addr == originator.s_addr)
+      return 1;
+  return 0;
+}
+
+unsigned int
+cluster_hash_key_make (struct cluster_list *cluster)
+{
+  unsigned int key = 0;
+  int length;
+  caddr_t pnt;
+
+  length = cluster->length;
+  pnt = (caddr_t) cluster->list;
+  
+  while (length)
+    key += pnt[--length];
+
+  return key;
+}
+
+int
+cluster_hash_cmp (struct cluster_list *cluster1, struct cluster_list *cluster2)
+{
+  if (cluster1->length == cluster2->length &&
+      memcmp (cluster1->list, cluster2->list, cluster1->length) == 0)
+    return 1;
+  return 0;
+}
+
+void
+cluster_free (struct cluster_list *cluster)
+{
+  if (cluster->list)
+    XFREE (MTYPE_CLUSTER_VAL, cluster->list);
+  XFREE (MTYPE_CLUSTER, cluster);
+}
+
+struct cluster_list *
+cluster_dup (struct cluster_list *cluster)
+{
+  struct cluster_list *new;
+
+  new = XMALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list));
+  memset (new, 0, sizeof (struct cluster_list));
+  new->length = cluster->length;
+
+  if (cluster->length)
+    {
+      new->list = XMALLOC (MTYPE_CLUSTER_VAL, cluster->length);
+      memcpy (new->list, cluster->list, cluster->length);
+    }
+  else
+    new->list = NULL;
+  
+  return new;
+}
+
+struct cluster_list *
+cluster_intern (struct cluster_list *cluster)
+{
+  struct cluster_list *find;
+
+  find = hash_get (cluster_hash, cluster, cluster_hash_alloc);
+  find->refcnt++;
+
+  return find;
+}
+
+void
+cluster_unintern (struct cluster_list *cluster)
+{
+  struct cluster_list *ret;
+
+  if (cluster->refcnt)
+    cluster->refcnt--;
+
+  if (cluster->refcnt == 0)
+    {
+      ret = hash_release (cluster_hash, cluster);
+      cluster_free (cluster);
+    }
+}
+
+void
+cluster_init ()
+{
+  cluster_hash = hash_create (cluster_hash_key_make, cluster_hash_cmp);
+}
+
+/* Unknown transit attribute. */
+struct hash *transit_hash;
+
+void
+transit_free (struct transit *transit)
+{
+  if (transit->val)
+    XFREE (MTYPE_TRANSIT_VAL, transit->val);
+  XFREE (MTYPE_TRANSIT, transit);
+}
+
+void *
+transit_hash_alloc (struct transit *transit)
+{
+  /* Transit structure is already allocated.  */
+  return transit;
+}
+
+struct transit *
+transit_intern (struct transit *transit)
+{
+  struct transit *find;
+
+  find = hash_get (transit_hash, transit, transit_hash_alloc);
+  if (find != transit)
+    transit_free (transit);
+  find->refcnt++;
+
+  return find;
+}
+
+void
+transit_unintern (struct transit *transit)
+{
+  struct transit *ret;
+
+  if (transit->refcnt)
+    transit->refcnt--;
+
+  if (transit->refcnt == 0)
+    {
+      ret = hash_release (transit_hash, transit);
+      transit_free (transit);
+    }
+}
+
+unsigned int
+transit_hash_key_make (struct transit *transit)
+{
+  unsigned int key = 0;
+  int length;
+  caddr_t pnt;
+
+  length = transit->length;
+  pnt = (caddr_t) transit->val;
+  
+  while (length)
+    key += pnt[--length];
+
+  return key;
+}
+
+int
+transit_hash_cmp (struct transit *transit1, struct transit *transit2)
+{
+  if (transit1->length == transit2->length &&
+      memcmp (transit1->val, transit2->val, transit1->length) == 0)
+    return 1;
+  return 0;
+}
+
+void
+transit_init ()
+{
+  transit_hash = hash_create (transit_hash_key_make, transit_hash_cmp);
+}
+
+/* Attribute hash routines. */
+
+struct hash *attrhash;
+
+unsigned int
+attrhash_key_make (struct attr *attr)
+{
+  unsigned int key = 0;
+
+  key += attr->origin;
+  key += attr->nexthop.s_addr;
+  key += attr->med;
+  key += attr->local_pref;
+  key += attr->aggregator_as;
+  key += attr->aggregator_addr.s_addr;
+  key += attr->weight;
+
+  key += attr->mp_nexthop_global_in.s_addr;
+  if (attr->aspath)
+    key += aspath_key_make (attr->aspath);
+  if (attr->community)
+    key += community_hash_make (attr->community);
+  if (attr->ecommunity)
+    key += ecommunity_hash_make (attr->ecommunity);
+  if (attr->cluster)
+    key += cluster_hash_key_make (attr->cluster);
+  if (attr->transit)
+    key += transit_hash_key_make (attr->transit);
+
+#ifdef HAVE_IPV6
+ {
+   int i;
+   
+   key += attr->mp_nexthop_len;
+   for (i = 0; i < 16; i++)
+     key += attr->mp_nexthop_global.s6_addr[i];
+   for (i = 0; i < 16; i++)
+     key += attr->mp_nexthop_local.s6_addr[i];
+ }
+#endif /* HAVE_IPV6 */
+
+  return key;
+}
+
+int
+attrhash_cmp (struct attr *attr1, struct attr *attr2)
+{
+  if (attr1->flag == attr2->flag
+      && attr1->origin == attr2->origin
+      && attr1->nexthop.s_addr == attr2->nexthop.s_addr
+      && attr1->med == attr2->med
+      && attr1->local_pref == attr2->local_pref
+      && attr1->aggregator_as == attr2->aggregator_as
+      && attr1->aggregator_addr.s_addr == attr2->aggregator_addr.s_addr
+      && attr1->weight == attr2->weight
+#ifdef HAVE_IPV6
+      && attr1->mp_nexthop_len == attr2->mp_nexthop_len
+      && IPV6_ADDR_SAME (&attr1->mp_nexthop_global, &attr2->mp_nexthop_global)
+      && IPV6_ADDR_SAME (&attr1->mp_nexthop_local, &attr2->mp_nexthop_local)
+#endif /* HAVE_IPV6 */
+      && IPV4_ADDR_SAME (&attr1->mp_nexthop_global_in, &attr2->mp_nexthop_global_in)
+      && attr1->aspath == attr2->aspath
+      && attr1->community == attr2->community
+      && attr1->ecommunity == attr2->ecommunity
+      && attr1->cluster == attr2->cluster
+      && attr1->transit == attr2->transit)
+    return 1;
+  else
+    return 0;
+}
+
+void
+attrhash_init ()
+{
+  attrhash = hash_create (attrhash_key_make, attrhash_cmp);
+}
+
+void
+attr_show_all_iterator (struct hash_backet *backet, struct vty *vty)
+{
+  struct attr *attr = backet->data;
+
+  vty_out (vty, "attr[%ld] nexthop %s%s", attr->refcnt, 
+	   inet_ntoa (attr->nexthop), VTY_NEWLINE);
+}
+
+void
+attr_show_all (struct vty *vty)
+{
+  hash_iterate (attrhash, 
+		(void (*)(struct hash_backet *, void *))
+		attr_show_all_iterator,
+		vty);
+}
+
+void *
+bgp_attr_hash_alloc (struct attr *val)
+{
+  struct attr *attr;
+
+  attr = XMALLOC (MTYPE_ATTR, sizeof (struct attr));
+  *attr = *val;
+  attr->refcnt = 0;
+  return attr;
+}
+
+/* Internet argument attribute. */
+struct attr *
+bgp_attr_intern (struct attr *attr)
+{
+  struct attr *find;
+
+  /* Intern referenced strucutre. */
+  if (attr->aspath)
+    {
+      if (! attr->aspath->refcnt)
+	attr->aspath = aspath_intern (attr->aspath);
+      else
+	attr->aspath->refcnt++;
+    }
+  if (attr->community)
+    {
+      if (! attr->community->refcnt)
+	attr->community = community_intern (attr->community);
+      else
+	attr->community->refcnt++;
+    }
+  if (attr->ecommunity)
+    {
+      if (! attr->ecommunity->refcnt)
+	attr->ecommunity = ecommunity_intern (attr->ecommunity);
+      else
+	attr->ecommunity->refcnt++;
+    }
+  if (attr->cluster)
+    {
+      if (! attr->cluster->refcnt)
+	attr->cluster = cluster_intern (attr->cluster);
+      else
+	attr->cluster->refcnt++;
+    }
+  if (attr->transit)
+    {
+      if (! attr->transit->refcnt)
+	attr->transit = transit_intern (attr->transit);
+      else
+	attr->transit->refcnt++;
+    }
+
+  find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc);
+  find->refcnt++;
+
+  return find;
+}
+
+/* Make network statement's attribute. */
+struct attr *
+bgp_attr_default_set (struct attr *attr, u_char origin)
+{
+  memset (attr, 0, sizeof (struct attr));
+
+  attr->origin = origin;
+  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
+  attr->aspath = aspath_empty ();
+  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
+  attr->weight = 32768;
+  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
+#ifdef HAVE_IPV6
+  attr->mp_nexthop_len = 16;
+#endif
+  return attr;
+}
+
+/* Make network statement's attribute. */
+struct attr *
+bgp_attr_default_intern (u_char origin)
+{
+  struct attr attr;
+  struct attr *new;
+
+  memset (&attr, 0, sizeof (struct attr));
+
+  attr.origin = origin;
+  attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
+  attr.aspath = aspath_empty ();
+  attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
+  attr.weight = 32768;
+  attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
+#ifdef HAVE_IPV6
+  attr.mp_nexthop_len = 16;
+#endif
+
+  new = bgp_attr_intern (&attr);
+  aspath_unintern (new->aspath);
+  return new;
+}
+
+struct attr *
+bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
+			   struct aspath *aspath,
+			   struct community *community, int as_set)
+{
+  struct attr attr;
+  struct attr *new;
+
+  memset (&attr, 0, sizeof (struct attr));
+
+  /* Origin attribute. */
+  attr.origin = origin;
+  attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
+
+  /* AS path attribute. */
+  if (aspath)
+    attr.aspath = aspath_intern (aspath);
+  else
+    attr.aspath = aspath_empty ();
+  attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
+
+  /* Next hop attribute.  */
+  attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
+
+  if (community)
+    {
+      attr.community = community;
+      attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
+    }
+
+  attr.weight = 32768;
+#ifdef HAVE_IPV6
+  attr.mp_nexthop_len = 16;
+#endif
+  if (! as_set)
+    attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
+  attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
+  if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
+    attr.aggregator_as = bgp->confed_id;
+  else
+    attr.aggregator_as = bgp->as;
+  attr.aggregator_addr = bgp->router_id;
+
+  new = bgp_attr_intern (&attr);
+  aspath_unintern (new->aspath);
+  return new;
+}
+
+/* Free bgp attribute and aspath. */
+void
+bgp_attr_unintern (struct attr *attr)
+{
+  struct attr *ret;
+  struct aspath *aspath;
+  struct community *community;
+  struct ecommunity *ecommunity;
+  struct cluster_list *cluster;
+  struct transit *transit;
+
+  /* Decrement attribute reference. */
+  attr->refcnt--;
+  aspath = attr->aspath;
+  community = attr->community;
+  ecommunity = attr->ecommunity;
+  cluster = attr->cluster;
+  transit = attr->transit;
+
+  /* If reference becomes zero then free attribute object. */
+  if (attr->refcnt == 0)
+    {    
+      ret = hash_release (attrhash, attr);
+      assert (ret != NULL);
+      XFREE (MTYPE_ATTR, attr);
+    }
+
+  /* aspath refcount shoud be decrement. */
+  if (aspath)
+    aspath_unintern (aspath);
+  if (community)
+    community_unintern (community);
+  if (ecommunity)
+    ecommunity_unintern (ecommunity);
+  if (cluster)
+    cluster_unintern (cluster);
+  if (transit)
+    transit_unintern (transit);
+}
+
+void
+bgp_attr_flush (struct attr *attr)
+{
+  if (attr->aspath && ! attr->aspath->refcnt)
+    aspath_free (attr->aspath);
+  if (attr->community && ! attr->community->refcnt)
+    community_free (attr->community);
+  if (attr->ecommunity && ! attr->ecommunity->refcnt)
+    ecommunity_free (attr->ecommunity);
+  if (attr->cluster && ! attr->cluster->refcnt)
+    cluster_free (attr->cluster);
+  if (attr->transit && ! attr->transit->refcnt)
+    transit_free (attr->transit);
+}
+
+/* Get origin attribute of the update message. */
+int
+bgp_attr_origin (struct peer *peer, bgp_size_t length, 
+		 struct attr *attr, u_char flag, u_char *startp)
+{
+  bgp_size_t total;
+
+  /* total is entire attribute length include Attribute Flags (1),
+     Attribute Type code (1) and Attribute length (1 or 2).  */
+  total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
+
+  /* If any recognized attribute has Attribute Flags that conflict
+     with the Attribute Type Code, then the Error Subcode is set to
+     Attribute Flags Error.  The Data field contains the erroneous
+     attribute (type, length and value). */
+  if (flag != BGP_ATTR_FLAG_TRANS)
+    {
+      zlog (peer->log, LOG_ERR, 
+	    "Origin attribute flag isn't transitive %d", flag);
+      bgp_notify_send_with_data (peer, 
+				 BGP_NOTIFY_UPDATE_ERR, 
+				 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+				 startp, total);
+      return -1;
+    }
+
+  /* If any recognized attribute has Attribute Length that conflicts
+     with the expected length (based on the attribute type code), then
+     the Error Subcode is set to Attribute Length Error.  The Data
+     field contains the erroneous attribute (type, length and
+     value). */
+  if (length != 1)
+    {
+      zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d",
+	    length);
+      bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, 
+				 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+				 startp, total);
+      return -1;
+    }
+
+  /* Fetch origin attribute. */
+  attr->origin = stream_getc (BGP_INPUT (peer));
+
+  /* If the ORIGIN attribute has an undefined value, then the Error
+     Subcode is set to Invalid Origin Attribute.  The Data field
+     contains the unrecognized attribute (type, length and value). */
+  if ((attr->origin != BGP_ORIGIN_IGP)
+      && (attr->origin != BGP_ORIGIN_EGP)
+      && (attr->origin != BGP_ORIGIN_INCOMPLETE))
+    {
+      zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d",
+	      attr->origin);
+
+      bgp_notify_send_with_data (peer, 
+				 BGP_NOTIFY_UPDATE_ERR, 
+				 BGP_NOTIFY_UPDATE_INVAL_ORIGIN,
+				 startp, total);
+      return -1;
+    }
+
+  /* Set oring attribute flag. */
+  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN);
+
+  return 0;
+}
+
+/* Parse AS path information.  This function is wrapper of
+   aspath_parse. */
+int
+bgp_attr_aspath (struct peer *peer, bgp_size_t length, 
+		 struct attr *attr, u_char flag, u_char *startp)
+{
+  struct bgp *bgp;
+  struct aspath *aspath;
+  bgp_size_t total;
+
+  total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
+
+  /* Flag check. */
+  if (CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL)
+      || ! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
+    {
+      zlog (peer->log, LOG_ERR, 
+	    "Origin attribute flag isn't transitive %d", flag);
+      bgp_notify_send_with_data (peer, 
+				 BGP_NOTIFY_UPDATE_ERR, 
+				 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+				 startp, total);
+      return -1;
+    }
+
+  /* In case of IBGP, length will be zero. */
+  attr->aspath = aspath_parse (stream_pnt (peer->ibuf), length);
+  if (! attr->aspath)
+    {
+      zlog (peer->log, LOG_ERR, "Malformed AS path length is %d", length);
+      bgp_notify_send (peer, 
+		       BGP_NOTIFY_UPDATE_ERR, 
+		       BGP_NOTIFY_UPDATE_MAL_AS_PATH);
+      return -1;
+    }
+
+  bgp = peer->bgp;
+    
+  /* First AS check for EBGP. */
+  if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
+    {
+      if (peer_sort (peer) == BGP_PEER_EBGP 
+	  && ! aspath_firstas_check (attr->aspath, peer->as))
+ 	{
+ 	  zlog (peer->log, LOG_ERR,
+ 		"%s incorrect first AS (must be %d)", peer->host, peer->as);
+ 	  bgp_notify_send (peer,
+ 			   BGP_NOTIFY_UPDATE_ERR,
+ 			   BGP_NOTIFY_UPDATE_MAL_AS_PATH);
+	  return -1;
+ 	}
+    }
+
+  /* local-as prepend */
+  if (peer->change_local_as &&
+      ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
+    {
+      aspath = aspath_dup (attr->aspath);
+      aspath = aspath_add_seq (aspath, peer->change_local_as);
+      aspath_unintern (attr->aspath);
+      attr->aspath = aspath_intern (aspath);
+    }
+
+  /* Forward pointer. */
+  stream_forward (peer->ibuf, length);
+
+  /* Set aspath attribute flag. */
+  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
+
+  return 0;
+}
+
+/* Nexthop attribute. */
+int
+bgp_attr_nexthop (struct peer *peer, bgp_size_t length, 
+		  struct attr *attr, u_char flag, u_char *startp)
+{
+  bgp_size_t total;
+
+  total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
+
+  /* Flag check. */
+  if (CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL)
+      || ! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
+    {
+      zlog (peer->log, LOG_ERR, 
+	    "Origin attribute flag isn't transitive %d", flag);
+      bgp_notify_send_with_data (peer, 
+				 BGP_NOTIFY_UPDATE_ERR, 
+				 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR,
+				 startp, total);
+      return -1;
+    }
+
+  /* Check nexthop attribute length. */
+  if (length != 4)
+    {
+      zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]",
+	      length);
+
+      bgp_notify_send_with_data (peer, 
+				 BGP_NOTIFY_UPDATE_ERR, 
+				 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+				 startp, total);
+      return -1;
+    }
+
+  attr->nexthop.s_addr = stream_get_ipv4 (peer->ibuf);
+  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
+
+  return 0;
+}
+
+/* MED atrribute. */
+int
+bgp_attr_med (struct peer *peer, bgp_size_t length, 
+	      struct attr *attr, u_char flag, u_char *startp)
+{
+  bgp_size_t total;
+
+  total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
+
+  /* Length check. */
+  if (length != 4)
+    {
+      zlog (peer->log, LOG_ERR, 
+	    "MED attribute length isn't four [%d]", length);
+      
+      bgp_notify_send_with_data (peer, 
+				 BGP_NOTIFY_UPDATE_ERR, 
+				 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+				 startp, total);
+      return -1;
+    }
+
+  attr->med = stream_getl (peer->ibuf);
+
+  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
+
+  return 0;
+}
+
+/* Local preference attribute. */
+int
+bgp_attr_local_pref (struct peer *peer, bgp_size_t length, 
+		     struct attr *attr, u_char flag)
+{
+  /* If it is contained in an UPDATE message that is received from an
+     external peer, then this attribute MUST be ignored by the
+     receiving speaker. */
+  if (peer_sort (peer) == BGP_PEER_EBGP)
+    {
+      stream_forward (peer->ibuf, length);
+      return 0;
+    }
+
+  if (length == 4) 
+    attr->local_pref = stream_getl (peer->ibuf);
+  else 
+    attr->local_pref = 0;
+
+  /* Set atomic aggregate flag. */
+  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
+
+  return 0;
+}
+
+/* Atomic aggregate. */
+int
+bgp_attr_atomic (struct peer *peer, bgp_size_t length, 
+		 struct attr *attr, u_char flag)
+{
+  if (length != 0)
+    {
+      zlog (peer->log, LOG_ERR, "Bad atomic aggregate length %d", length);
+
+      bgp_notify_send (peer, 
+		       BGP_NOTIFY_UPDATE_ERR, 
+		       BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
+      return -1;
+    }
+
+  /* Set atomic aggregate flag. */
+  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
+
+  return 0;
+}
+
+/* Aggregator attribute */
+int
+bgp_attr_aggregator (struct peer *peer, bgp_size_t length,
+		     struct attr *attr, u_char flag)
+{
+  if (length != 6)
+    {
+      zlog (peer->log, LOG_ERR, "Aggregator length is not 6 [%d]", length);
+
+      bgp_notify_send (peer,
+		       BGP_NOTIFY_UPDATE_ERR,
+		       BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
+      return -1;
+    }
+  attr->aggregator_as = stream_getw (peer->ibuf);
+  attr->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
+
+  /* Set atomic aggregate flag. */
+  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
+
+  return 0;
+}
+
+/* Community attribute. */
+int
+bgp_attr_community (struct peer *peer, bgp_size_t length, 
+		    struct attr *attr, u_char flag)
+{
+  if (length == 0)
+    attr->community = NULL;
+  else
+    {
+      attr->community = community_parse (stream_pnt (peer->ibuf), length);
+      stream_forward (peer->ibuf, length);
+    }
+
+  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
+
+  return 0;
+}
+
+/* Originator ID attribute. */
+int
+bgp_attr_originator_id (struct peer *peer, bgp_size_t length, 
+			struct attr *attr, u_char flag)
+{
+  if (length != 4)
+    {
+      zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length);
+
+      bgp_notify_send (peer, 
+		       BGP_NOTIFY_UPDATE_ERR, 
+		       BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
+      return -1;
+    }
+
+  attr->originator_id.s_addr = stream_get_ipv4 (peer->ibuf);
+
+  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
+
+  return 0;
+}
+
+/* Cluster list attribute. */
+int
+bgp_attr_cluster_list (struct peer *peer, bgp_size_t length, 
+		       struct attr *attr, u_char flag)
+{
+  /* Check length. */
+  if (length % 4)
+    {
+      zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length);
+
+      bgp_notify_send (peer, 
+		       BGP_NOTIFY_UPDATE_ERR, 
+		       BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
+      return -1;
+    }
+
+  attr->cluster = cluster_parse (stream_pnt (peer->ibuf), length);
+
+  stream_forward (peer->ibuf, length);;
+
+  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST);
+
+  return 0;
+}
+
+/* Multiprotocol reachability information parse. */
+int
+bgp_mp_reach_parse (struct peer *peer, bgp_size_t length, struct attr *attr,
+		    struct bgp_nlri *mp_update)
+{
+  u_int16_t afi;
+  u_char safi;
+  u_char snpa_num;
+  u_char snpa_len;
+  u_char *lim;
+  bgp_size_t nlri_len;
+  int ret;
+  struct stream *s;
+  
+  /* Set end of packet. */
+  s = peer->ibuf;
+  lim = stream_pnt (s) + length;
+
+  /* Load AFI, SAFI. */
+  afi = stream_getw (s);
+  safi = stream_getc (s);
+
+  /* Get nexthop length. */
+  attr->mp_nexthop_len = stream_getc (s);
+
+  /* Nexthop length check. */
+  switch (attr->mp_nexthop_len)
+    {
+    case 4:
+      stream_get (&attr->mp_nexthop_global_in, s, 4);
+      break;
+    case 12:
+      {
+	u_int32_t rd_high;
+	u_int32_t rd_low;
+
+	rd_high = stream_getl (s);
+	rd_low = stream_getl (s);
+	stream_get (&attr->mp_nexthop_global_in, s, 4);
+      }
+      break;
+#ifdef HAVE_IPV6
+    case 16:
+      stream_get (&attr->mp_nexthop_global, s, 16);
+      break;
+    case 32:
+      stream_get (&attr->mp_nexthop_global, s, 16);
+      stream_get (&attr->mp_nexthop_local, s, 16);
+      if (! IN6_IS_ADDR_LINKLOCAL (&attr->mp_nexthop_local))
+	{
+	  char buf1[INET6_ADDRSTRLEN];
+	  char buf2[INET6_ADDRSTRLEN];
+
+	  if (BGP_DEBUG (update, UPDATE_IN))
+	    zlog_warn ("%s got two nexthop %s %s but second one is not a link-local nexthop", peer->host,
+		       inet_ntop (AF_INET6, &attr->mp_nexthop_global,
+				  buf1, INET6_ADDRSTRLEN),
+		       inet_ntop (AF_INET6, &attr->mp_nexthop_local,
+				  buf2, INET6_ADDRSTRLEN));
+
+	  attr->mp_nexthop_len = 16;
+	}
+      break;
+#endif /* HAVE_IPV6 */
+    default:
+      zlog_info ("Wrong multiprotocol next hop length: %d", 
+		 attr->mp_nexthop_len);
+      return -1;
+      break;
+    }
+
+  snpa_num = stream_getc (s);
+
+  while (snpa_num--)
+    {
+      snpa_len = stream_getc (s);
+      stream_forward (s, (snpa_len + 1) >> 1);
+    }
+  
+  /* If peer is based on old draft-00. I read NLRI length from the
+     packet. */
+  if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
+    {
+      bgp_size_t nlri_total_len;
+      nlri_total_len = stream_getw (s);
+    }
+
+  nlri_len = lim - stream_pnt (s);
+ 
+  if (safi != BGP_SAFI_VPNV4)
+    {
+      ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), nlri_len);
+      if (ret < 0)
+	return -1;
+    }
+
+  mp_update->afi = afi;
+  mp_update->safi = safi;
+  mp_update->nlri = stream_pnt (s);
+  mp_update->length = nlri_len;
+
+  stream_forward (s, nlri_len);
+
+  return 0;
+}
+
+/* Multiprotocol unreachable parse */
+int
+bgp_mp_unreach_parse (struct peer *peer, int length, 
+		      struct bgp_nlri *mp_withdraw)
+{
+  struct stream *s;
+  u_int16_t afi;
+  u_char safi;
+  u_char *lim;
+  u_int16_t withdraw_len;
+  int ret;
+
+  s = peer->ibuf;
+  lim = stream_pnt (s) + length;
+
+  afi = stream_getw (s);
+  safi = stream_getc (s);
+
+  withdraw_len = lim - stream_pnt (s);
+
+  if (safi != BGP_SAFI_VPNV4)
+    {
+      ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), withdraw_len);
+      if (ret < 0)
+	return -1;
+    }
+
+  mp_withdraw->afi = afi;
+  mp_withdraw->safi = safi;
+  mp_withdraw->nlri = stream_pnt (s);
+  mp_withdraw->length = withdraw_len;
+
+  stream_forward (s, withdraw_len);
+
+  return 0;
+}
+
+/* Extended Community attribute. */
+int
+bgp_attr_ext_communities (struct peer *peer, bgp_size_t length, 
+			  struct attr *attr, u_char flag)
+{
+  if (length == 0)
+    attr->ecommunity = NULL;
+  else
+    {
+      attr->ecommunity = ecommunity_parse (stream_pnt (peer->ibuf), length);
+      stream_forward (peer->ibuf, length);
+    }
+  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
+
+  return 0;
+}
+
+/* BGP unknown attribute treatment. */
+int
+bgp_attr_unknown (struct peer *peer, struct attr *attr, u_char flag,
+		  u_char type, bgp_size_t length, u_char *startp)
+{
+  bgp_size_t total;
+  struct transit *transit;
+
+  if (BGP_DEBUG (events, EVENTS))
+    zlog (peer->log, LOG_INFO, 
+	  "Unknown attribute type %d length %d is received", type, length);
+
+  /* Forward read pointer of input stream. */
+  stream_forward (peer->ibuf, length);
+
+  /* Adjest total length to include type and length. */
+  total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
+
+  /* If any of the mandatory well-known attributes are not recognized,
+     then the Error Subcode is set to Unrecognized Well-known
+     Attribute.  The Data field contains the unrecognized attribute
+     (type, length and value). */
+  if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL))
+    {
+      /* Adjust startp to do not include flag value. */
+      bgp_notify_send_with_data (peer, 
+				 BGP_NOTIFY_UPDATE_ERR, 
+				 BGP_NOTIFY_UPDATE_UNREC_ATTR,
+				 startp, total);
+      return -1;
+    }
+
+  /* Unrecognized non-transitive optional attributes must be quietly
+     ignored and not passed along to other BGP peers. */
+  if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS))
+    return 0;
+
+  /* If a path with recognized transitive optional attribute is
+     accepted and passed along to other BGP peers and the Partial bit
+     in the Attribute Flags octet is set to 1 by some previous AS, it
+     is not set back to 0 by the current AS. */
+  SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL);
+
+  /* Store transitive attribute to the end of attr->transit. */
+  if (! attr->transit)
+    {
+      attr->transit = XMALLOC (MTYPE_TRANSIT, sizeof (struct transit));
+      memset (attr->transit, 0, sizeof (struct transit));
+    }
+
+  transit = attr->transit;
+
+  if (transit->val)
+    transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val, 
+			     transit->length + total);
+  else
+    transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total);
+
+  memcpy (transit->val + transit->length, startp, total);
+  transit->length += total;
+
+  return 0;
+}
+
+/* Read attribute of update packet.  This function is called from
+   bgp_update() in bgpd.c.  */
+int
+bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
+		struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw)
+{
+  int ret;
+  u_char flag;
+  u_char type;
+  bgp_size_t length;
+  u_char *startp, *endp;
+  u_char *attr_endp;
+  u_char seen[BGP_ATTR_BITMAP_SIZE];
+
+  /* Initialize bitmap. */
+  memset (seen, 0, BGP_ATTR_BITMAP_SIZE);
+
+  /* End pointer of BGP attribute. */
+  endp = BGP_INPUT_PNT (peer) + size;
+
+  /* Get attributes to the end of attribute length. */
+  while (BGP_INPUT_PNT (peer) < endp)
+    {
+      /* Check remaining length check.*/
+      if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN)
+	{
+	  zlog (peer->log, LOG_WARNING, 
+		"%s error BGP attribute length %d is smaller than min len",
+		peer->host, endp - STREAM_PNT (BGP_INPUT (peer)));
+
+	  bgp_notify_send (peer, 
+			   BGP_NOTIFY_UPDATE_ERR, 
+			   BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
+	  return -1;
+	}
+
+      /* Fetch attribute flag and type. */
+      startp = BGP_INPUT_PNT (peer);
+      flag = stream_getc (BGP_INPUT (peer));
+      type = stream_getc (BGP_INPUT (peer));
+
+      /* Check extended attribue length bit. */
+      if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
+	length = stream_getw (BGP_INPUT (peer));
+      else
+	length = stream_getc (BGP_INPUT (peer));
+      
+      /* If any attribute appears more than once in the UPDATE
+	 message, then the Error Subcode is set to Malformed Attribute
+	 List. */
+
+      if (CHECK_BITMAP (seen, type))
+	{
+	  zlog (peer->log, LOG_WARNING,
+		"%s error BGP attribute type %d appears twice in a message",
+		peer->host, type);
+
+	  bgp_notify_send (peer, 
+			   BGP_NOTIFY_UPDATE_ERR, 
+			   BGP_NOTIFY_UPDATE_MAL_ATTR);
+	  return -1;
+	}
+
+      /* Set type to bitmap to check duplicate attribute.  `type' is
+	 unsigned char so it never overflow bitmap range. */
+
+      SET_BITMAP (seen, type);
+
+      /* Overflow check. */
+      attr_endp =  BGP_INPUT_PNT (peer) + length;
+
+      if (attr_endp > endp)
+	{
+	  zlog (peer->log, LOG_WARNING, 
+		"%s BGP type %d length %d is too large, attribute total length is %d.  attr_endp is %p.  endp is %p", peer->host, type, length, size, attr_endp, endp);
+	  bgp_notify_send (peer, 
+			   BGP_NOTIFY_UPDATE_ERR, 
+			   BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
+	  return -1;
+	}
+
+      /* OK check attribute and store it's value. */
+      switch (type)
+	{
+	case BGP_ATTR_ORIGIN:
+	  ret = bgp_attr_origin (peer, length, attr, flag, startp);
+	  break;
+	case BGP_ATTR_AS_PATH:
+	  ret = bgp_attr_aspath (peer, length, attr, flag, startp);
+	  break;
+	case BGP_ATTR_NEXT_HOP:	
+	  ret = bgp_attr_nexthop (peer, length, attr, flag, startp);
+	  break;
+	case BGP_ATTR_MULTI_EXIT_DISC:
+	  ret = bgp_attr_med (peer, length, attr, flag, startp);
+	  break;
+	case BGP_ATTR_LOCAL_PREF:
+	  ret = bgp_attr_local_pref (peer, length, attr, flag);
+	  break;
+	case BGP_ATTR_ATOMIC_AGGREGATE:
+	  ret = bgp_attr_atomic (peer, length, attr, flag);
+	  break;
+	case BGP_ATTR_AGGREGATOR:
+	  ret = bgp_attr_aggregator (peer, length, attr, flag);
+	  break;
+	case BGP_ATTR_COMMUNITIES:
+	  ret = bgp_attr_community (peer, length, attr, flag);
+	  break;
+	case BGP_ATTR_ORIGINATOR_ID:
+	  ret = bgp_attr_originator_id (peer, length, attr, flag);
+	  break;
+	case BGP_ATTR_CLUSTER_LIST:
+	  ret = bgp_attr_cluster_list (peer, length, attr, flag);
+	  break;
+	case BGP_ATTR_MP_REACH_NLRI:
+	  ret = bgp_mp_reach_parse (peer, length, attr, mp_update);
+	  break;
+	case BGP_ATTR_MP_UNREACH_NLRI:
+	  ret = bgp_mp_unreach_parse (peer, length, mp_withdraw);
+	  break;
+	case BGP_ATTR_EXT_COMMUNITIES:
+	  ret = bgp_attr_ext_communities (peer, length, attr, flag);
+	  break;
+	default:
+	  ret = bgp_attr_unknown (peer, attr, flag, type, length, startp);
+	  break;
+	}
+
+      /* If error occured immediately return to the caller. */
+      if (ret < 0)
+	return ret;
+
+      /* Check the fetched length. */
+      if (BGP_INPUT_PNT (peer) != attr_endp)
+	{
+	  zlog (peer->log, LOG_WARNING, 
+		"%s BGP attribute fetch error", peer->host);
+	  bgp_notify_send (peer, 
+			   BGP_NOTIFY_UPDATE_ERR, 
+			   BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
+	  return -1;
+	}
+    }
+
+  /* Check final read pointer is same as end pointer. */
+  if (BGP_INPUT_PNT (peer) != endp)
+    {
+      zlog (peer->log, LOG_WARNING, 
+	    "%s BGP attribute length mismatch", peer->host);
+      bgp_notify_send (peer, 
+		       BGP_NOTIFY_UPDATE_ERR, 
+		       BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
+      return -1;
+    }
+
+  /* Finally intern unknown attribute. */
+  if (attr->transit)
+    attr->transit = transit_intern (attr->transit);
+
+  return 0;
+}
+
+/* Well-known attribute check. */
+int
+bgp_attr_check (struct peer *peer, struct attr *attr)
+{
+  u_char type = 0;
+  
+  if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN)))
+    type = BGP_ATTR_ORIGIN;
+
+  if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)))
+    type = BGP_ATTR_AS_PATH;
+
+  if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)))
+    type = BGP_ATTR_NEXT_HOP;
+
+  if (peer_sort (peer) == BGP_PEER_IBGP
+      && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)))
+    type = BGP_ATTR_LOCAL_PREF;
+
+  if (type)
+    {
+      zlog (peer->log, LOG_WARNING, 
+	    "%s Missing well-known attribute %d.",
+	    peer->host, type);
+      bgp_notify_send_with_data (peer, 
+				 BGP_NOTIFY_UPDATE_ERR, 
+				 BGP_NOTIFY_UPDATE_MISS_ATTR,
+				 &type, 1);
+      return -1;
+    }
+  return 0;
+}
+
+int stream_put_prefix (struct stream *, struct prefix *);
+
+/* Make attribute packet. */
+bgp_size_t
+bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
+		      struct stream *s, struct attr *attr, struct prefix *p,
+		      afi_t afi, safi_t safi, struct peer *from,
+		      struct prefix_rd *prd, u_char *tag)
+{
+  unsigned long cp;
+  struct aspath *aspath;
+
+  if (! bgp)
+    bgp = bgp_get_default ();
+
+  /* Remember current pointer. */
+  cp = stream_get_putp (s);
+
+  /* Origin attribute. */
+  stream_putc (s, BGP_ATTR_FLAG_TRANS);
+  stream_putc (s, BGP_ATTR_ORIGIN);
+  stream_putc (s, 1);
+  stream_putc (s, attr->origin);
+
+  /* AS path attribute. */
+
+  /* If remote-peer is EBGP */
+  if (peer_sort (peer) == BGP_PEER_EBGP
+      && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
+	  || attr->aspath->length == 0)
+      && ! (CHECK_FLAG (from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
+	    && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)))
+    {    
+      aspath = aspath_dup (attr->aspath);
+
+      if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
+	{
+	  /* Strip the confed info, and then stuff our path CONFED_ID
+	     on the front */
+	  aspath = aspath_delete_confed_seq (aspath);
+	  aspath = aspath_add_seq (aspath, bgp->confed_id);
+	}
+      else
+	{
+	  aspath = aspath_add_seq (aspath, peer->local_as);
+	  if (peer->change_local_as)
+	    aspath = aspath_add_seq (aspath, peer->change_local_as);
+	}
+    }
+  else if (peer_sort (peer) == BGP_PEER_CONFED)
+    {
+      /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */
+      aspath = aspath_dup (attr->aspath);
+      aspath = aspath_add_confed_seq (aspath, peer->local_as);
+    }
+  else
+    aspath = attr->aspath;
+
+  /* AS path attribute extended length bit check. */
+  if (aspath->length > 255)
+    {
+      stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
+      stream_putc (s, BGP_ATTR_AS_PATH);
+      stream_putw (s, aspath->length);
+    }
+  else
+    {
+      stream_putc (s, BGP_ATTR_FLAG_TRANS);
+      stream_putc(s, BGP_ATTR_AS_PATH);
+      stream_putc (s, aspath->length);
+    }
+  stream_put (s, aspath->data, aspath->length);
+
+  if (aspath != attr->aspath)
+    aspath_free (aspath);
+
+  /* Nexthop attribute. */
+  if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP)
+    {
+      stream_putc (s, BGP_ATTR_FLAG_TRANS);
+      stream_putc (s, BGP_ATTR_NEXT_HOP);
+      stream_putc (s, 4);
+      if (safi == SAFI_MPLS_VPN)
+	{
+	  if (attr->nexthop.s_addr == 0)
+	    stream_put_ipv4 (s, peer->nexthop.v4.s_addr);
+	  else
+	    stream_put_ipv4 (s, attr->nexthop.s_addr);
+	}
+      else
+	stream_put_ipv4 (s, attr->nexthop.s_addr);
+    }
+
+  /* MED attribute. */
+  if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
+    {
+      stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
+      stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
+      stream_putc (s, 4);
+      stream_putl (s, attr->med);
+    }
+
+  /* Local preference. */
+  if (peer_sort (peer) == BGP_PEER_IBGP ||
+      peer_sort (peer) == BGP_PEER_CONFED)
+    {
+      stream_putc (s, BGP_ATTR_FLAG_TRANS);
+      stream_putc (s, BGP_ATTR_LOCAL_PREF);
+      stream_putc (s, 4);
+      stream_putl (s, attr->local_pref);
+    }
+
+  /* Atomic aggregate. */
+  if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
+    {
+      stream_putc (s, BGP_ATTR_FLAG_TRANS);
+      stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
+      stream_putc (s, 0);
+    }
+
+  /* Aggregator. */
+  if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
+    {
+      stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
+      stream_putc (s, BGP_ATTR_AGGREGATOR);
+      stream_putc (s, 6);
+      stream_putw (s, attr->aggregator_as);
+      stream_put_ipv4 (s, attr->aggregator_addr.s_addr);
+    }
+
+  /* Community attribute. */
+  if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY) 
+      && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)))
+    {
+      if (attr->community->size * 4 > 255)
+	{
+	  stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
+	  stream_putc (s, BGP_ATTR_COMMUNITIES);
+	  stream_putw (s, attr->community->size * 4);
+	}
+      else
+	{
+	  stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
+	  stream_putc (s, BGP_ATTR_COMMUNITIES);
+	  stream_putc (s, attr->community->size * 4);
+	}
+      stream_put (s, attr->community->val, attr->community->size * 4);
+    }
+
+  /* Route Reflector. */
+  if (peer_sort (peer) == BGP_PEER_IBGP
+      && from
+      && peer_sort (from) == BGP_PEER_IBGP)
+    {
+      /* Originator ID. */
+      stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
+      stream_putc (s, BGP_ATTR_ORIGINATOR_ID);
+      stream_putc (s, 4);
+
+      if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
+	stream_put_in_addr (s, &attr->originator_id);
+      else
+	{
+	  if (from)
+	    stream_put_in_addr (s, &from->remote_id);
+	  else
+	    stream_put_in_addr (s, &attr->originator_id);
+	}
+
+      /* Cluster list. */
+      stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
+      stream_putc (s, BGP_ATTR_CLUSTER_LIST);
+      
+      if (attr->cluster)
+	{
+	  stream_putc (s, attr->cluster->length + 4);
+	  /* If this peer configuration's parent BGP has cluster_id. */
+	  if (bgp->config & BGP_CONFIG_CLUSTER_ID)
+	    stream_put_in_addr (s, &bgp->cluster_id);
+	  else
+	    stream_put_in_addr (s, &bgp->router_id);
+	  stream_put (s, attr->cluster->list, attr->cluster->length);
+	}
+      else
+	{
+	  stream_putc (s, 4);
+	  /* If this peer configuration's parent BGP has cluster_id. */
+	  if (bgp->config & BGP_CONFIG_CLUSTER_ID)
+	    stream_put_in_addr (s, &bgp->cluster_id);
+	  else
+	    stream_put_in_addr (s, &bgp->router_id);
+	}
+    }
+
+#ifdef HAVE_IPV6
+  /* If p is IPv6 address put it into attribute. */
+  if (p->family == AF_INET6)
+    {
+      unsigned long sizep;
+      unsigned long draftp = 0;
+
+      stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
+      stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
+      sizep = stream_get_putp (s);
+      stream_putc (s, 0);	/* Length of this attribute. */
+      stream_putw (s, AFI_IP6);	/* AFI */
+      stream_putc (s, safi);	/* SAFI */
+
+      stream_putc (s, attr->mp_nexthop_len);
+
+      if (attr->mp_nexthop_len == 16)
+	stream_put (s, &attr->mp_nexthop_global, 16);
+      else if (attr->mp_nexthop_len == 32)
+	{
+	  stream_put (s, &attr->mp_nexthop_global, 16);
+	  stream_put (s, &attr->mp_nexthop_local, 16);
+	}
+      
+      /* SNPA */
+      stream_putc (s, 0);
+
+      /* In case of old draft BGP-4+. */
+      if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
+	{
+	  draftp = stream_get_putp (s);
+	  stream_putw (s, 0);
+	}
+      
+      /* Prefix write. */
+      stream_put_prefix (s, p);
+
+      /* Set MP attribute length. */
+      stream_putc_at (s, sizep, (stream_get_putp (s) - sizep) - 1);
+
+      /* In case of old draft BGP-4+. */
+      if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
+	stream_putw_at (s, draftp, (stream_get_putp (s) - draftp) - 2);
+    }
+#endif /* HAVE_IPV6 */
+
+  if (p->family == AF_INET && safi == SAFI_MULTICAST)
+    {
+      unsigned long sizep;
+      unsigned long draftp = 0;
+
+      stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
+      stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
+      sizep = stream_get_putp (s);
+      stream_putc (s, 0);	/* Length of this attribute. */
+      stream_putw (s, AFI_IP);	/* AFI */
+      stream_putc (s, SAFI_MULTICAST);	/* SAFI */
+
+      stream_putc (s, 4);
+      stream_put_ipv4 (s, attr->nexthop.s_addr);
+
+      /* SNPA */
+      stream_putc (s, 0);
+
+      /* In case of old draft BGP-4+. */
+      if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
+	{
+	  draftp = stream_get_putp (s);
+	  stream_putw (s, 0);
+	}
+      
+      /* Prefix write. */
+      stream_put_prefix (s, p);
+
+      /* Set MP attribute length. */
+      stream_putc_at (s, sizep, (stream_get_putp (s) - sizep) - 1);
+
+      /* In case of old draft BGP-4+. */
+      if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
+	stream_putw_at (s, draftp, (stream_get_putp (s) - draftp) - 2);
+    }
+
+  if (p->family == AF_INET && safi == SAFI_MPLS_VPN)
+    {
+      unsigned long sizep;
+      unsigned long draftp = 0;
+
+      stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
+      stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
+      sizep = stream_get_putp (s);
+      stream_putc (s, 0);	/* Length of this attribute. */
+      stream_putw (s, AFI_IP);	/* AFI */
+      stream_putc (s, BGP_SAFI_VPNV4);	/* SAFI */
+
+      stream_putc (s, 12);
+      stream_putl (s, 0);
+      stream_putl (s, 0);
+      stream_put (s, &attr->mp_nexthop_global_in, 4);
+
+      /* SNPA */
+      stream_putc (s, 0);
+
+      /* In case of old draft BGP-4+. */
+      if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
+	{
+	  draftp = stream_get_putp (s);
+	  stream_putw (s, 0);
+	}
+      
+      /* Tag, RD, Prefix write. */
+      stream_putc (s, p->prefixlen + 88);
+      stream_put (s, tag, 3);
+      stream_put (s, prd->val, 8);
+      stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
+
+      /* Set MP attribute length. */
+      stream_putc_at (s, sizep, (stream_get_putp (s) - sizep) - 1);
+
+      /* In case of old draft BGP-4+. */
+      if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
+	stream_putw_at (s, draftp, (stream_get_putp (s) - draftp) - 2);
+    }
+
+  /* Extended Communities attribute. */
+  if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY) 
+      && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)))
+    {
+      if (attr->ecommunity->size * 8 > 255)
+	{
+	  stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
+	  stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
+	  stream_putw (s, attr->ecommunity->size * 8);
+	}
+      else
+	{
+	  stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
+	  stream_putc (s, BGP_ATTR_EXT_COMMUNITIES);
+	  stream_putc (s, attr->ecommunity->size * 8);
+	}
+      stream_put (s, attr->ecommunity->val, attr->ecommunity->size * 8);
+    }
+
+  /* Unknown transit attribute. */
+  if (attr->transit)
+    stream_put (s, attr->transit->val, attr->transit->length);
+
+  /* Return total size of attribute. */
+  return stream_get_putp (s) - cp;
+}
+
+bgp_size_t
+bgp_packet_withdraw (struct peer *peer, struct stream *s, struct prefix *p,
+		     afi_t afi, safi_t safi, struct prefix_rd *prd,
+		     u_char *tag)
+{
+  unsigned long cp;
+  unsigned long attrlen_pnt;
+  bgp_size_t size;
+
+  cp = stream_get_putp (s);
+
+  stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
+  stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
+
+  attrlen_pnt = stream_get_putp (s);
+  stream_putc (s, 0);		/* Length of this attribute. */
+
+  stream_putw (s, family2afi (p->family));
+
+  if (safi == SAFI_MPLS_VPN)
+    {
+      /* SAFI */
+      stream_putc (s, BGP_SAFI_VPNV4);
+
+      /* prefix. */
+      stream_putc (s, p->prefixlen + 88);
+      stream_put (s, tag, 3);
+      stream_put (s, prd->val, 8);
+      stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
+    }
+  else
+    {
+      /* SAFI */
+      stream_putc (s, safi);
+
+      /* prefix */
+      stream_put_prefix (s, p);
+    }
+
+  /* Set MP attribute length. */
+  size = stream_get_putp (s) - attrlen_pnt - 1;
+  stream_putc_at (s, attrlen_pnt, size);
+
+  return stream_get_putp (s) - cp;
+}
+
+/* Initialization of attribute. */
+void
+bgp_attr_init ()
+{
+  void attrhash_init ();
+
+  aspath_init ();
+  attrhash_init ();
+  community_init ();
+  ecommunity_init ();
+  cluster_init ();
+  transit_init ();
+}
+
+/* Make attribute packet. */
+void
+bgp_dump_routes_attr (struct stream *s, struct attr *attr)
+{
+  unsigned long cp;
+  unsigned long len;
+  struct aspath *aspath;
+
+  /* Remember current pointer. */
+  cp = stream_get_putp (s);
+
+  /* Place holder of length. */
+  stream_putw (s, 0);
+
+  /* Origin attribute. */
+  stream_putc (s, BGP_ATTR_FLAG_TRANS);
+  stream_putc (s, BGP_ATTR_ORIGIN);
+  stream_putc (s, 1);
+  stream_putc (s, attr->origin);
+
+  aspath = attr->aspath;
+
+  if (aspath->length > 255)
+    {
+      stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
+      stream_putc (s, BGP_ATTR_AS_PATH);
+      stream_putw (s, aspath->length);
+    }
+  else
+    {
+      stream_putc (s, BGP_ATTR_FLAG_TRANS);
+      stream_putc (s, BGP_ATTR_AS_PATH);
+      stream_putc (s, aspath->length);
+    }
+  stream_put (s, aspath->data, aspath->length);
+
+  /* Nexthop attribute. */
+  stream_putc (s, BGP_ATTR_FLAG_TRANS);
+  stream_putc (s, BGP_ATTR_NEXT_HOP);
+  stream_putc (s, 4);
+  stream_put_ipv4 (s, attr->nexthop.s_addr);
+
+  /* MED attribute. */
+  if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
+    {
+      stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
+      stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC);
+      stream_putc (s, 4);
+      stream_putl (s, attr->med);
+    }
+
+  /* Local preference. */
+  if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
+    {
+      stream_putc (s, BGP_ATTR_FLAG_TRANS);
+      stream_putc (s, BGP_ATTR_LOCAL_PREF);
+      stream_putc (s, 4);
+      stream_putl (s, attr->local_pref);
+    }
+
+  /* Atomic aggregate. */
+  if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))
+    {
+      stream_putc (s, BGP_ATTR_FLAG_TRANS);
+      stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE);
+      stream_putc (s, 0);
+    }
+
+  /* Aggregator. */
+  if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
+    {
+      stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
+      stream_putc (s, BGP_ATTR_AGGREGATOR);
+      stream_putc (s, 6);
+      stream_putw (s, attr->aggregator_as);
+      stream_put_ipv4 (s, attr->aggregator_addr.s_addr);
+    }
+
+  /* Community attribute. */
+  if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))
+    {
+      if (attr->community->size * 4 > 255)
+	{
+	  stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
+	  stream_putc (s, BGP_ATTR_COMMUNITIES);
+	  stream_putw (s, attr->community->size * 4);
+	}
+      else
+	{
+	  stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
+	  stream_putc (s, BGP_ATTR_COMMUNITIES);
+	  stream_putc (s, attr->community->size * 4);
+	}
+      stream_put (s, attr->community->val, attr->community->size * 4);
+    }
+
+  /* Return total size of attribute. */
+  len = stream_get_putp (s) - cp - 2;
+  stream_putw_at (s, cp, len);
+}
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
new file mode 100644
index 0000000..9c5bf87
--- /dev/null
+++ b/bgpd/bgp_attr.h
@@ -0,0 +1,125 @@
+/* BGP attributes. 
+   Copyright (C) 1996, 97, 98 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+/* Simple bit mapping. */
+#define BITMAP_NBBY 8
+
+#define SET_BITMAP(MAP, NUM) \
+        SET_FLAG (MAP[(NUM) / BITMAP_NBBY], 1 << ((NUM) % BITMAP_NBBY))
+
+#define CHECK_BITMAP(MAP, NUM) \
+        CHECK_FLAG (MAP[(NUM) / BITMAP_NBBY], 1 << ((NUM) % BITMAP_NBBY))
+
+/* BGP Attribute type range. */
+#define BGP_ATTR_TYPE_RANGE     256
+#define BGP_ATTR_BITMAP_SIZE    (BGP_ATTR_TYPE_RANGE / BITMAP_NBBY)
+
+/* BGP Attribute flags. */
+#define BGP_ATTR_FLAG_OPTIONAL  0x80	/* Attribute is optional. */
+#define BGP_ATTR_FLAG_TRANS     0x40	/* Attribute is transitive. */
+#define BGP_ATTR_FLAG_PARTIAL   0x20	/* Attribute is partial. */
+#define BGP_ATTR_FLAG_EXTLEN    0x10	/* Extended length flag. */
+
+/* BGP attribute header must bigger than 2. */
+#define BGP_ATTR_MIN_LEN        2       /* Attribute flag and type. */
+
+/* BGP attribute structure. */
+struct attr
+{
+  /* Reference count of this attribute. */
+  unsigned long refcnt;
+
+  /* Flag of attribute is set or not. */
+  u_int32_t flag;
+
+  /* Attributes. */
+  u_char origin;
+  struct in_addr nexthop;
+  u_int32_t med;
+  u_int32_t local_pref;
+  as_t aggregator_as;
+  struct in_addr aggregator_addr;
+  u_int32_t weight;
+  struct in_addr originator_id;
+  struct cluster_list *cluster;
+
+  u_char mp_nexthop_len;
+#ifdef HAVE_IPV6
+  struct in6_addr mp_nexthop_global;
+  struct in6_addr mp_nexthop_local;
+#endif /* HAVE_IPV6 */
+  struct in_addr mp_nexthop_global_in;
+  struct in_addr mp_nexthop_local_in;
+
+  /* AS Path structure */
+  struct aspath *aspath;
+
+  /* Community structure */
+  struct community *community;	
+
+  /* Extended Communities attribute. */
+  struct ecommunity *ecommunity;
+
+  /* Unknown transitive attribute. */
+  struct transit *transit;
+};
+
+/* Router Reflector related structure. */
+struct cluster_list
+{
+  unsigned long refcnt;
+  int length;
+  struct in_addr *list;
+};
+
+/* Unknown transit attribute. */
+struct transit
+{
+  unsigned long refcnt;
+  int length;
+  u_char *val;
+};
+
+#define ATTR_FLAG_BIT(X)  (1 << ((X) - 1))
+
+/* Prototypes. */
+void bgp_attr_init ();
+int bgp_attr_parse (struct peer *, struct attr *, bgp_size_t,
+		    struct bgp_nlri *, struct bgp_nlri *);
+int bgp_attr_check (struct peer *, struct attr *);
+struct attr *bgp_attr_intern (struct attr *attr);
+void bgp_attr_unintern (struct attr *);
+void bgp_attr_flush (struct attr *);
+struct attr *bgp_attr_default_set (struct attr *attr, u_char);
+struct attr *bgp_attr_default_intern (u_char);
+struct attr *bgp_attr_aggregate_intern (struct bgp *, u_char, struct aspath *, struct community *, int as_set);
+bgp_size_t bgp_packet_attribute (struct bgp *bgp, struct peer *, struct stream *, struct attr *, struct prefix *, afi_t, safi_t, struct peer *, struct prefix_rd *, u_char *);
+bgp_size_t bgp_packet_withdraw (struct peer *peer, struct stream *s, struct prefix *p, afi_t, safi_t, struct prefix_rd *, u_char *);
+void bgp_dump_routes_attr (struct stream *, struct attr *);
+unsigned int attrhash_key_make (struct attr *);
+int attrhash_cmp (struct attr *, struct attr *);
+void attr_show_all (struct vty *);
+
+/* Cluster list prototypes. */
+int cluster_loop_check (struct cluster_list *, struct in_addr);
+void cluster_unintern (struct cluster_list *);
+
+/* Transit attribute prototypes. */
+void transit_unintern (struct transit *);
diff --git a/bgpd/bgp_btoa.c b/bgpd/bgp_btoa.c
new file mode 100644
index 0000000..7c70881
--- /dev/null
+++ b/bgpd/bgp_btoa.c
@@ -0,0 +1,291 @@
+/* BGP dump to ascii converter
+   Copyright (C) 1999 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "zebra.h"
+#include "stream.h"
+#include "log.h"
+#include "prefix.h"
+#include "command.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_dump.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_aspath.h"
+
+enum MRT_MSG_TYPES {
+   MSG_NULL,
+   MSG_START,                   /* sender is starting up */
+   MSG_DIE,                     /* receiver should shut down */
+   MSG_I_AM_DEAD,               /* sender is shutting down */
+   MSG_PEER_DOWN,               /* sender's peer is down */
+   MSG_PROTOCOL_BGP,            /* msg is a BGP packet */
+   MSG_PROTOCOL_RIP,            /* msg is a RIP packet */
+   MSG_PROTOCOL_IDRP,           /* msg is an IDRP packet */
+   MSG_PROTOCOL_RIPNG,          /* msg is a RIPNG packet */
+   MSG_PROTOCOL_BGP4PLUS,       /* msg is a BGP4+ packet */
+   MSG_PROTOCOL_BGP4PLUS_01,    /* msg is a BGP4+ (draft 01) packet */
+   MSG_PROTOCOL_OSPF,           /* msg is an OSPF packet */
+   MSG_TABLE_DUMP               /* routing table dump */
+};
+
+int
+attr_parse (struct stream *s, u_int16_t len)
+{
+  u_int flag;
+  u_int type;
+  u_int16_t length;
+  u_int16_t lim;
+
+  lim = s->getp + len;
+
+  printf ("attr_parse s->getp %d, len %d, lim %d\n", s->getp, len, lim);
+
+  while (s->getp < lim)
+    {
+      flag = stream_getc (s);
+      type = stream_getc (s);
+
+      if (flag & ATTR_FLAG_EXTLEN)
+	length = stream_getw (s);
+      else
+	length = stream_getc (s);
+
+      printf ("FLAG: %d\n", flag);
+      printf ("TYPE: %d\n", type);
+      printf ("Len: %d\n", length);
+
+      switch (type)
+	{
+	case BGP_ATTR_ORIGIN:
+	  {
+	    u_char origin;
+	    origin = stream_getc (s);
+	    printf ("ORIGIN: %d\n", origin);
+	  }
+	  break;
+	case BGP_ATTR_AS_PATH:
+	  {
+	    struct aspath aspath;
+
+	    aspath.data = (s->data + s->getp);
+	    aspath.length = length;
+	    aspath.str = aspath_make_str_count (&aspath);
+	    printf ("ASPATH: %s\n", aspath.str);
+	    free (aspath.str);
+	    
+	    stream_forward (s, length);
+	  }
+	  break;
+	case BGP_ATTR_NEXT_HOP:	
+	  {
+	    struct in_addr nexthop;
+	    nexthop.s_addr = stream_get_ipv4 (s);
+	    printf ("NEXTHOP: %s\n", inet_ntoa (nexthop));
+	    /* stream_forward (s, length); */
+	  }
+	  break;
+	default:
+	  stream_forward (s, length);
+	  break;
+	}
+    }
+
+  return 0;
+}
+
+int
+main (int argc, char **argv)
+{
+  int ret;
+  FILE *fp;
+  struct stream *s;
+  time_t now;
+  int type;
+  int subtype;
+  int len;
+  int source_as;
+  int dest_as;
+  int ifindex;
+  int family;
+  struct in_addr sip;
+  struct in_addr dip;
+  u_int16_t viewno, seq_num;
+  struct prefix_ipv4 p;
+
+  s = stream_new (10000);
+
+  if (argc != 2)
+    {
+      fprintf (stderr, "Usage: %s FILENAME\n", argv[0]);
+      exit (1);
+    }
+  fp = fopen (argv[1], "r");
+  if (!fp)
+    {
+      perror ("fopen");
+      exit (1);
+    }
+  
+  while (1)
+    {
+      stream_reset (s);
+
+      ret = fread (s->data, 12, 1, fp);
+      if (feof (fp))
+	{
+	  printf ("END OF FILE\n");
+	  break;
+	}
+      if (ferror (fp))
+	{
+	  printf ("ERROR OF FREAD\n");
+	  break;
+	}
+
+      /* Extract header. */
+      now = stream_getl (s);
+      type = stream_getw (s);
+      subtype = stream_getw (s);
+      len = stream_getl (s);
+
+      printf ("TIME: %s", ctime (&now));
+
+      /* printf ("TYPE: %d/%d\n", type, subtype); */
+
+      if (type == MSG_PROTOCOL_BGP4MP)
+	printf ("TYPE: BGP4MP");
+      else if (type == MSG_TABLE_DUMP)
+	printf ("TYPE: MSG_TABLE_DUMP");
+      else
+	printf ("TYPE: Unknown %d", type);
+
+      if (type == MSG_TABLE_DUMP)
+	switch (subtype)
+	  {
+	  case AFI_IP:
+	    printf ("/AFI_IP\n");
+	    break;
+	  case AFI_IP6:
+	    printf ("/AFI_IP6\n");
+	    break;
+	  default:
+	    printf ("/UNKNOWN %d", subtype);
+	    break;
+	  }
+      else
+	{
+	  switch (subtype)
+	    {
+	    case BGP4MP_STATE_CHANGE:
+	      printf ("/CHANGE\n");
+	      break;
+	    case BGP4MP_MESSAGE:
+	      printf ("/MESSAGE\n");
+	      break;
+	    case BGP4MP_ENTRY:
+	      printf ("/ENTRY\n");
+	      break;
+	    case BGP4MP_SNAPSHOT:
+	      printf ("/SNAPSHOT\n");
+	      break;
+	    default:
+	      printf ("/UNKNOWN %d", subtype);
+	      break;
+	    }
+	}
+
+      printf ("len: %d\n", len);
+
+      ret = fread (s->data + 12, len, 1, fp);
+      if (feof (fp))
+	{
+	  printf ("ENDOF FILE 2\n");
+	  break;
+	}
+      if (ferror (fp))
+	{
+	  printf ("ERROR OF FREAD 2\n");
+	  break;
+	}
+
+      /* printf ("now read %d\n", len); */
+
+      if (type == MSG_TABLE_DUMP)
+	{
+	  u_char status;
+	  time_t originated;
+	  struct in_addr peer;
+	  u_int16_t attrlen;
+
+	  viewno = stream_getw (s);
+	  seq_num = stream_getw (s);
+	  printf ("VIEW: %d\n", viewno);
+	  printf ("SEQUENCE: %d\n", seq_num);
+
+	  /* start */
+	  while (s->getp < len - 16)
+	    {
+	      p.prefix.s_addr = stream_get_ipv4 (s);
+	      p.prefixlen = stream_getc (s);
+	      printf ("PREFIX: %s/%d\n", inet_ntoa (p.prefix), p.prefixlen);
+
+	      status = stream_getc (s);
+	      originated = stream_getl (s);
+	      peer.s_addr = stream_get_ipv4 (s);
+	      source_as = stream_getw(s);
+
+	      printf ("FROM: %s AS%d\n", inet_ntoa (peer), source_as);
+	      printf ("ORIGINATED: %s", ctime (&originated));
+
+	      attrlen = stream_getw (s);
+	      printf ("ATTRLEN: %d\n", attrlen);
+
+	      attr_parse (s, attrlen);
+
+	      printf ("STATUS: 0x%x\n", status);
+	    }
+	}
+      else
+	{
+	  source_as = stream_getw (s);
+	  dest_as = stream_getw (s);
+	  printf ("source_as: %d\n", source_as);
+	  printf ("dest_as: %d\n", dest_as);
+
+	  ifindex = stream_getw (s);
+	  family = stream_getw (s);
+
+	  printf ("ifindex: %d\n", ifindex);
+	  printf ("family: %d\n", family);
+
+	  sip.s_addr = stream_get_ipv4 (s);
+	  dip.s_addr = stream_get_ipv4 (s);
+	  
+	  printf ("saddr: %s\n", inet_ntoa (sip));
+	  printf ("daddr: %s\n", inet_ntoa (dip));
+
+	  printf ("\n");
+	}
+    }
+  fclose (fp);
+  return 0;
+}
diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c
new file mode 100644
index 0000000..0b6a2e8
--- /dev/null
+++ b/bgpd/bgp_clist.c
@@ -0,0 +1,905 @@
+/* BGP community-list and extcommunity-list.
+   Copyright (C) 1999 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "command.h"
+#include "prefix.h"
+#include "memory.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_community.h"
+#include "bgpd/bgp_ecommunity.h"
+#include "bgpd/bgp_aspath.h"
+#include "bgpd/bgp_regex.h"
+#include "bgpd/bgp_clist.h"
+
+/* Lookup master structure for community-list or
+   extcommunity-list.  */
+struct community_list_master *
+community_list_master_lookup (struct community_list_handler *ch, int style)
+{
+  if (ch)
+    switch (style)
+      {
+      case COMMUNITY_LIST_STANDARD:
+      case COMMUNITY_LIST_EXPANDED:
+      case COMMUNITY_LIST_AUTO:
+	return &ch->community_list;
+	break;
+      case EXTCOMMUNITY_LIST_STANDARD:
+      case EXTCOMMUNITY_LIST_EXPANDED:
+      case EXTCOMMUNITY_LIST_AUTO:
+	return &ch->extcommunity_list;
+      }
+  return NULL;
+}
+
+/* Allocate a new community list entry.  */
+struct community_entry *
+community_entry_new ()
+{
+  struct community_entry *new;
+
+  new = XMALLOC (MTYPE_COMMUNITY_LIST_ENTRY, sizeof (struct community_entry));
+  memset (new, 0, sizeof (struct community_entry));
+  return new;
+}
+
+/* Free community list entry.  */
+void
+community_entry_free (struct community_entry *entry)
+{
+  switch (entry->style)
+    {
+    case COMMUNITY_LIST_STANDARD:
+      if (entry->u.com)
+	community_free (entry->u.com);
+      break;
+    case EXTCOMMUNITY_LIST_STANDARD:
+      /* In case of standard extcommunity-list, configuration string
+	 is made by ecommunity_ecom2str().  */
+      if (entry->config)
+	XFREE (MTYPE_ECOMMUNITY_STR, entry->config);
+      if (entry->u.ecom)
+	ecommunity_free (entry->u.ecom);
+      break;
+    case COMMUNITY_LIST_EXPANDED:
+    case EXTCOMMUNITY_LIST_EXPANDED:
+      if (entry->config)
+	XFREE (MTYPE_COMMUNITY_LIST_CONFIG, entry->config);
+      if (entry->reg)
+	bgp_regex_free (entry->reg);
+    default:
+      break;
+    }
+  XFREE (MTYPE_COMMUNITY_LIST_ENTRY, entry);
+}
+
+/* Allocate a new community-list.  */
+struct community_list *
+community_list_new ()
+{
+  struct community_list *new;
+
+  new = XMALLOC (MTYPE_COMMUNITY_LIST, sizeof (struct community_list));
+  memset (new, 0, sizeof (struct community_list));
+  return new;
+}
+
+/* Free community-list.  */
+void
+community_list_free (struct community_list *list)
+{
+  if (list->name)
+    XFREE (MTYPE_COMMUNITY_LIST_NAME, list->name);
+  XFREE (MTYPE_COMMUNITY_LIST, list);
+}
+
+struct community_list *
+community_list_insert (struct community_list_handler *ch,
+		       char *name, int style)
+{
+  int i;
+  long number;
+  struct community_list *new;
+  struct community_list *point;
+  struct community_list_list *list;
+  struct community_list_master *cm;
+
+  /* Lookup community-list master.  */
+  cm = community_list_master_lookup (ch, style);
+  if (! cm)
+    return NULL;
+
+  /* Allocate new community_list and copy given name. */
+  new = community_list_new ();
+  new->name = XSTRDUP (MTYPE_COMMUNITY_LIST_NAME, name);
+
+  /* If name is made by all digit character.  We treat it as
+     number. */
+  for (number = 0, i = 0; i < strlen (name); i++)
+    {
+      if (isdigit ((int) name[i]))
+	number = (number * 10) + (name[i] - '0');
+      else
+	break;
+    }
+
+  /* In case of name is all digit character */
+  if (i == strlen (name))
+    {
+      new->sort = COMMUNITY_LIST_NUMBER;
+
+      /* Set access_list to number list. */
+      list = &cm->num;
+
+      for (point = list->head; point; point = point->next)
+	if (atol (point->name) >= number)
+	  break;
+    }
+  else
+    {
+      new->sort = COMMUNITY_LIST_STRING;
+
+      /* Set access_list to string list. */
+      list = &cm->str;
+  
+      /* Set point to insertion point. */
+      for (point = list->head; point; point = point->next)
+	if (strcmp (point->name, name) >= 0)
+	  break;
+    }
+
+  /* Link to upper list.  */
+  new->parent = list;
+
+  /* In case of this is the first element of master. */
+  if (list->head == NULL)
+    {
+      list->head = list->tail = new;
+      return new;
+    }
+
+  /* In case of insertion is made at the tail of access_list. */
+  if (point == NULL)
+    {
+      new->prev = list->tail;
+      list->tail->next = new;
+      list->tail = new;
+      return new;
+    }
+
+  /* In case of insertion is made at the head of access_list. */
+  if (point == list->head)
+    {
+      new->next = list->head;
+      list->head->prev = new;
+      list->head = new;
+      return new;
+    }
+
+  /* Insertion is made at middle of the access_list. */
+  new->next = point;
+  new->prev = point->prev;
+
+  if (point->prev)
+    point->prev->next = new;
+  point->prev = new;
+
+  return new;
+}
+
+struct community_list *
+community_list_lookup (struct community_list_handler *ch,
+		       char *name, int style)
+{
+  struct community_list *list;
+  struct community_list_master *cm;
+
+  if (! name)
+    return NULL;
+
+  cm = community_list_master_lookup (ch, style);
+  if (! cm)
+    return NULL;
+
+  for (list = cm->num.head; list; list = list->next)
+    if (strcmp (list->name, name) == 0)
+      return list;
+  for (list = cm->str.head; list; list = list->next)
+    if (strcmp (list->name, name) == 0)
+      return list;
+
+  return NULL;
+}
+
+struct community_list *
+community_list_get (struct community_list_handler *ch, char *name, int style)
+{
+  struct community_list *list;
+
+  list = community_list_lookup (ch, name, style);
+  if (! list)
+    list = community_list_insert (ch, name, style);
+  return list;
+}
+
+void
+community_list_delete (struct community_list *list)
+{
+  struct community_list_list *clist;
+  struct community_entry *entry, *next;
+
+  for (entry = list->head; entry; entry = next)
+    {
+      next = entry->next;
+      community_entry_free (entry);
+    }
+
+  clist = list->parent;
+
+  if (list->next)
+    list->next->prev = list->prev;
+  else
+    clist->tail = list->prev;
+
+  if (list->prev)
+    list->prev->next = list->next;
+  else
+    clist->head = list->next;
+
+  community_list_free (list);
+}
+
+int 
+community_list_empty_p (struct community_list *list)
+{
+  return (list->head == NULL && list->tail == NULL) ? 1 : 0;
+}
+
+/* Add community-list entry to the list.  */
+static void
+community_list_entry_add (struct community_list *list, 
+			  struct community_entry *entry)
+{
+  entry->next = NULL;
+  entry->prev = list->tail;
+
+  if (list->tail)
+    list->tail->next = entry;
+  else
+    list->head = entry;
+  list->tail = entry;
+}
+
+/* Delete community-list entry from the list.  */
+static void
+community_list_entry_delete (struct community_list *list,
+			     struct community_entry *entry, int style)
+{
+  if (entry->next)
+    entry->next->prev = entry->prev;
+  else
+    list->tail = entry->prev;
+
+  if (entry->prev)
+    entry->prev->next = entry->next;
+  else
+    list->head = entry->next;
+
+  community_entry_free (entry);
+
+  if (community_list_empty_p (list))
+    community_list_delete (list);
+}
+
+/* Lookup community-list entry from the list.  */
+static struct community_entry *
+community_list_entry_lookup (struct community_list *list, void *arg,
+			     int direct)
+{
+  struct community_entry *entry;
+
+  for (entry = list->head; entry; entry = entry->next)
+    {
+      switch (entry->style)
+	{
+	case COMMUNITY_LIST_STANDARD:
+	  if (community_cmp (entry->u.com, arg))
+	    return entry;
+	  break;
+	case EXTCOMMUNITY_LIST_STANDARD:
+	  if (ecommunity_cmp (entry->u.ecom, arg))
+	    return entry;
+	  break;
+	case COMMUNITY_LIST_EXPANDED:
+	case EXTCOMMUNITY_LIST_EXPANDED:
+	  if (strcmp (entry->config, arg) == 0)
+	    return entry;
+	  break;
+	default:
+	  break;
+	}
+    }
+  return NULL;
+}
+
+/* Internal function to perform regular expression match for community
+   attribute.  */
+static int
+community_regexp_match (struct community *com, regex_t *reg)
+{
+  char *str;
+
+  /* When there is no communities attribute it is treated as empty
+     string.  */
+  if (com == NULL || com->size == 0)
+    str = "";
+  else
+    str = community_str (com);
+
+  /* Regular expression match.  */
+  if (regexec (reg, str, 0, NULL, 0) == 0)
+    return 1;
+
+  /* No match.  */
+  return 0;
+}
+
+/* Delete community attribute using regular expression match.  Return
+   modified communites attribute.  */
+static struct community *
+community_regexp_delete (struct community *com, regex_t *reg)
+{
+  int i;
+  u_int32_t comval;
+  /* Maximum is "65535:65535" + '\0'. */
+  char c[12];
+  char *str;
+
+  if (! com)
+    return NULL;
+
+  i = 0;
+  while (i < com->size)
+    {
+      memcpy (&comval, com_nthval (com, i), sizeof (u_int32_t));
+      comval = ntohl (comval);
+
+      switch (comval)
+	{
+	case COMMUNITY_INTERNET:
+	  str = "internet";
+	  break;
+	case COMMUNITY_NO_EXPORT:
+	  str = "no-export";
+	  break;
+	case COMMUNITY_NO_ADVERTISE:
+	  str = "no-advertise";
+	  break;
+	case COMMUNITY_LOCAL_AS:
+	  str = "local-AS";
+	  break;
+	default:
+	  sprintf (c, "%d:%d", (comval >> 16) & 0xFFFF, comval & 0xFFFF);
+	  str = c;
+	  break;
+	}
+
+      if (regexec (reg, str, 0, NULL, 0) == 0)
+	community_del_val (com, com_nthval (com, i));
+      else
+	i++;
+    }
+  return com;
+}
+
+/* When given community attribute matches to the community-list return
+   1 else return 0.  */
+int
+community_list_match (struct community *com, struct community_list *list)
+{
+  struct community_entry *entry;
+
+  for (entry = list->head; entry; entry = entry->next)
+    {
+      if (entry->any)
+	return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
+
+      if (entry->style == COMMUNITY_LIST_STANDARD)
+	{
+	  if (community_include (entry->u.com, COMMUNITY_INTERNET))
+	    return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
+
+	  if (community_match (com, entry->u.com))
+	    return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
+	}
+      else if (entry->style == COMMUNITY_LIST_EXPANDED)
+	{
+	  if (community_regexp_match (com, entry->reg))
+	    return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
+	}
+    }
+  return 0;
+}
+
+/* Perform exact matching.  In case of expanded community-list, do
+   same thing as community_list_match().  */
+int
+community_list_exact_match (struct community *com, struct community_list *list)
+{
+  struct community_entry *entry;
+
+  for (entry = list->head; entry; entry = entry->next)
+    {
+      if (entry->any)
+	return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
+
+      if (entry->style == COMMUNITY_LIST_STANDARD)
+	{
+	  if (community_include (entry->u.com, COMMUNITY_INTERNET))
+	    return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
+
+	  if (community_cmp (com, entry->u.com))
+	    return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
+	}
+      else if (entry->style == COMMUNITY_LIST_EXPANDED)
+	{
+	  if (community_regexp_match (com, entry->reg))
+	    return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
+	}
+    }
+  return 0;
+}
+
+/* Delete all permitted communities in the list from com1 */
+struct community *
+community_list_match_delete (struct community *com,
+			     struct community_list *list)
+{
+  struct community_entry *entry;
+
+  for (entry = list->head; entry; entry = entry->next)
+    {
+      if (entry->any && entry->direct == COMMUNITY_PERMIT)
+	{
+	  /* This is a tricky part.  Currently only
+	     route_set_community_delete() uses this function.  In the
+	     function com->size is zero, it free the community
+	     structure.  */
+	  com->size = 0;
+	  return com;
+	}
+
+      if (entry->style == COMMUNITY_LIST_STANDARD)
+	{
+	  if (entry->direct == COMMUNITY_PERMIT)
+	    community_delete (com, entry->u.com);
+	}
+      else if (entry->style == COMMUNITY_LIST_EXPANDED)
+	{
+	  if (entry->direct == COMMUNITY_PERMIT)
+	    community_regexp_delete (com, entry->reg);
+	}
+    }
+  return com;
+}
+
+/* To avoid duplicated entry in the community-list, this function
+   compares specified entry to existing entry.  */
+int
+community_list_dup_check (struct community_list *list, 
+			  struct community_entry *new)
+{
+  struct community_entry *entry;
+  
+  for (entry = list->head; entry; entry = entry->next)
+    {
+      if (entry->style != new->style)
+	continue;
+
+      if (entry->direct != new->direct)
+	continue;
+
+      if (entry->any != new->any)
+	continue;
+
+      if (entry->any)
+	return 1;
+
+      switch (entry->style)
+	{
+	case COMMUNITY_LIST_STANDARD:
+	  if (community_cmp (entry->u.com, new->u.com))
+	    return 1;
+	  break;
+	case EXTCOMMUNITY_LIST_STANDARD:
+	  if (ecommunity_cmp (entry->u.ecom, new->u.ecom))
+	    return 1;
+	  break;
+	case COMMUNITY_LIST_EXPANDED:
+	case EXTCOMMUNITY_LIST_EXPANDED:
+	  if (strcmp (entry->config, new->config) == 0)
+	    return 1;
+	  break;
+	default:
+	  break;
+	}
+    }
+  return 0;
+}
+
+/* Set community-list.  */
+int
+community_list_set (struct community_list_handler *ch,
+		    char *name, char *str, int direct, int style)
+{
+  struct community_entry *entry;
+  struct community_list *list;
+  struct community *com;
+  regex_t *regex;
+
+  entry = NULL;
+
+  /* Get community list. */
+  list = community_list_get (ch, name, style);
+
+  /* When community-list already has entry, new entry should have same
+     style.  If you want to have mixed style community-list, you can
+     comment out this check.  */
+  if (! community_list_empty_p (list))
+    {
+      struct community_entry *first;
+
+      first = list->head;
+
+      if (style == COMMUNITY_LIST_AUTO)
+	style = first->style;
+      else if (style != first->style)
+	{
+	  return (first->style == COMMUNITY_LIST_STANDARD
+		  ? COMMUNITY_LIST_ERR_STANDARD_CONFLICT
+		  : COMMUNITY_LIST_ERR_EXPANDED_CONFLICT);
+	}
+    }
+
+  /* When str is NULL, it is matches any.  */
+  if (! str)
+    {
+      entry = community_entry_new ();
+      entry->direct = direct;
+      entry->any = 1;
+      if (style == COMMUNITY_LIST_AUTO)
+	entry->style = COMMUNITY_LIST_STANDARD;
+      else
+	entry->style = style;
+    }
+  else
+    {
+      /* Standard community-list parse.  String must be converted into
+	 community structure without problem.  */
+      if (style == COMMUNITY_LIST_STANDARD || style == COMMUNITY_LIST_AUTO)
+	{
+	  com = community_str2com (str);
+	  if (com)
+	    {
+	      entry = community_entry_new ();
+	      entry->u.com = com;
+	      entry->direct = direct;
+	      entry->style = COMMUNITY_LIST_STANDARD;
+	    }
+	  else if (style == COMMUNITY_LIST_STANDARD)
+	    return COMMUNITY_LIST_ERR_MALFORMED_VAL;
+	  
+	  /* We can't convert string into communities value.  When
+	     community-list type is auto, fall dawn to regular expression
+	     match.  */
+	}
+
+      /* Expanded community-list parse.  String may include regular
+	 expression.  */
+      if (! entry && (style == COMMUNITY_LIST_EXPANDED
+		      || style == COMMUNITY_LIST_AUTO))
+	{
+	  regex = bgp_regcomp (str);
+	  if (regex)
+	    {
+	      entry = community_entry_new ();
+	      entry->reg = regex;
+	      entry->config = XSTRDUP (MTYPE_COMMUNITY_LIST_CONFIG, str);
+	      entry->direct = direct;
+	      entry->style = COMMUNITY_LIST_EXPANDED;
+	    }
+	  else
+	    return COMMUNITY_LIST_ERR_MALFORMED_VAL;
+	}
+    }
+
+  /* Do not put duplicated community entry.  */
+  if (community_list_dup_check (list, entry))
+    community_entry_free (entry);
+  else
+    community_list_entry_add (list, entry);
+
+  return 0;
+}
+
+/* Unset community-list.  When str is NULL, delete all of
+   community-list entry belongs to the specified name.  */
+int
+community_list_unset (struct community_list_handler *ch,
+		      char *name, char *str, int direct, int style)
+{
+  struct community_entry *entry;
+  struct community_list *list;
+  struct community *com;
+  regex_t *regex;
+
+  entry = NULL;
+
+  /* Lookup community list.  */
+  list = community_list_lookup (ch, name, style);
+  if (list == NULL)
+    return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
+
+  /* Delete all of entry belongs to this community-list.  */
+  if (! str)
+    {
+      community_list_delete (list);
+      return 0;
+    }
+
+  /* Community list string is specified.  Lookup entry from community
+     list.  */
+  if (style == COMMUNITY_LIST_STANDARD || style == COMMUNITY_LIST_AUTO)
+    {
+      com = community_str2com (str);
+      if (com)
+	{
+	  entry = community_list_entry_lookup (list, com, direct);
+	  community_free (com);
+	}
+      else if (style == COMMUNITY_LIST_STANDARD)
+	return COMMUNITY_LIST_ERR_MALFORMED_VAL;
+
+      /* If we can't convert string into community and community-list
+	 type is auto, fall dawn to expanded community-list.  */
+    }
+
+  /* Expanded community-list parse.  String may include regular
+     expression.  */
+  if (! entry 
+      && (style == COMMUNITY_LIST_EXPANDED || style == COMMUNITY_LIST_AUTO))
+    {
+      regex = bgp_regcomp (str);
+      if (regex)
+	{
+	  entry = community_list_entry_lookup (list, str, direct);
+	  bgp_regex_free (regex);
+	}
+      else
+	return COMMUNITY_LIST_ERR_MALFORMED_VAL;
+    }
+
+  if (! entry)
+    return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
+
+  community_list_entry_delete (list, entry, style);
+
+  return 0;
+}
+
+/* Set extcommunity-list.  */
+int
+extcommunity_list_set (struct community_list_handler *ch,
+		       char *name, char *str, int direct, int style)
+{
+  struct community_entry *entry;
+  struct community_list *list;
+  struct ecommunity *ecom;
+  regex_t *regex;
+
+  entry = NULL;
+
+  /* Get community list. */
+  list = community_list_get (ch, name, style);
+
+  /* When community-list already has entry, new entry should have same
+     style.  If you want to have mixed style community-list, you can
+     comment out this check.  */
+  if (! community_list_empty_p (list))
+    {
+      struct community_entry *first;
+
+      first = list->head;
+
+      if (style == EXTCOMMUNITY_LIST_AUTO)
+	style = first->style;
+      else if (style != first->style)
+	{
+	  return (first->style == EXTCOMMUNITY_LIST_STANDARD
+		  ? COMMUNITY_LIST_ERR_STANDARD_CONFLICT
+		  : COMMUNITY_LIST_ERR_EXPANDED_CONFLICT);
+	}
+    }
+
+  /* When str is NULL, it is matches any.  */
+  if (! str)
+    {
+      entry = community_entry_new ();
+      entry->direct = direct;
+      entry->any = 1;
+      if (style == EXTCOMMUNITY_LIST_AUTO)
+	entry->style = EXTCOMMUNITY_LIST_STANDARD;
+      else
+	entry->style = style;
+    }
+  else
+    {
+      /* Standard extcommunity-list parse.  String is converted into
+	 ecommunity structure.  */
+      if (style == EXTCOMMUNITY_LIST_STANDARD
+	  || style == EXTCOMMUNITY_LIST_AUTO)
+	{
+	  /* Type is unknown.  String includes keyword.  */
+	  ecom = ecommunity_str2com (str, 0, 1);
+	  if (ecom)
+	    {
+	      entry = community_entry_new ();
+	      entry->config 
+		= ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_COMMUNITY_LIST);
+	      ecom->str = ecommunity_ecom2str (ecom, ECOMMUNITY_FORMAT_DISPLAY);
+	      entry->u.ecom = ecom;
+	      entry->direct = direct;
+	      entry->style = EXTCOMMUNITY_LIST_STANDARD;
+	    }
+	  else if (style == EXTCOMMUNITY_LIST_STANDARD)
+	    return COMMUNITY_LIST_ERR_MALFORMED_VAL;
+
+	  /* We can't convert string into communities value.  When
+	     community-list type is auto, fall dawn to regular expression
+	     match.  */
+	}
+
+      /* Expanded extcommunity-list parse.  String may include regular
+	 expression.  */
+      if (! entry && (style == EXTCOMMUNITY_LIST_EXPANDED
+		      || style == EXTCOMMUNITY_LIST_AUTO))
+	{
+	  regex = bgp_regcomp (str);
+	  if (regex)
+	    {
+	      entry = community_entry_new ();
+	      entry->reg = regex;
+	      entry->config = XSTRDUP (MTYPE_COMMUNITY_LIST_CONFIG, str);
+	      entry->direct = direct;
+	      entry->style = EXTCOMMUNITY_LIST_EXPANDED;
+	    }
+	  else
+	    return COMMUNITY_LIST_ERR_MALFORMED_VAL;
+	}
+    }
+
+  /* Do not put duplicated community entry.  */
+  if (community_list_dup_check (list, entry))
+    community_entry_free (entry);
+  else
+    community_list_entry_add (list, entry);
+
+  return 0;
+}
+
+/* Unset extcommunity-list.  When str is NULL, delete all of
+   extcommunity-list entry belongs to the specified name.  */
+int
+extcommunity_list_unset (struct community_list_handler *ch,
+			 char *name, char *str, int direct, int style)
+{
+  struct community_entry *entry;
+  struct community_list *list;
+  struct ecommunity *ecom = NULL;
+  regex_t *regex;
+
+  entry = NULL;
+
+  /* Lookup extcommunity list.  */
+  list = community_list_lookup (ch, name, style);
+  if (list == NULL)
+    return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
+
+  /* Delete all of entry belongs to this extcommunity-list.  */
+  if (! str)
+    {
+      community_list_delete (list);
+      return 0;
+    }
+
+  /* Community list string is specified.  Lookup entry from community
+     list.  */
+  if (style == EXTCOMMUNITY_LIST_STANDARD || style == EXTCOMMUNITY_LIST_AUTO)
+    {
+      ecom = ecommunity_str2com (str, 0, 1);
+      if (ecom)
+	{
+	  entry = community_list_entry_lookup (list, ecom, direct);
+	  ecommunity_free (ecom);
+	}
+      else if (style == COMMUNITY_LIST_STANDARD)
+	return COMMUNITY_LIST_ERR_MALFORMED_VAL;
+
+      /* If we can't convert string into community and community-list
+	 type is auto, fall dawn to expanded community-list.  */
+    }
+
+  /* Expanded community-list parse.  String may include regular
+     expression.  */
+  if (! entry 
+      && (style == COMMUNITY_LIST_EXPANDED || style == COMMUNITY_LIST_AUTO))
+    {
+      regex = bgp_regcomp (str);
+      if (regex)
+	{
+	  entry = community_list_entry_lookup (list, str, direct);
+	  bgp_regex_free (regex);
+	}
+      else
+	return COMMUNITY_LIST_ERR_MALFORMED_VAL;
+    }
+
+  if (! entry)
+    return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
+
+  community_list_entry_delete (list, entry, style);
+
+  return 0;
+}
+
+/* Initializa community-list.  Return community-list handler.  */
+struct community_list_handler *
+community_list_init ()
+{
+  struct community_list_handler *ch;
+  ch = XCALLOC (MTYPE_COMMUNITY_LIST_HANDLER,
+		sizeof (struct community_list_handler));
+  return ch;
+}
+
+/* Terminate community-list.  */
+void
+community_list_terminate (struct community_list_handler *ch)
+{
+  struct community_list_master *cm;
+  struct community_list *list;
+
+  cm = &ch->community_list;
+  while ((list = cm->num.head) != NULL)
+    community_list_delete (list);
+  while ((list = cm->str.head) != NULL)
+    community_list_delete (list);
+
+  cm = &ch->extcommunity_list;
+  while ((list = cm->num.head) != NULL)
+    community_list_delete (list);
+  while ((list = cm->str.head) != NULL)
+    community_list_delete (list);
+
+  XFREE (MTYPE_COMMUNITY_LIST_HANDLER, ch);
+}
diff --git a/bgpd/bgp_clist.h b/bgpd/bgp_clist.h
new file mode 100644
index 0000000..ffc707c
--- /dev/null
+++ b/bgpd/bgp_clist.h
@@ -0,0 +1,143 @@
+/* BGP Community list.
+   Copyright (C) 1999 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+/* Community-list deny and permit.  */
+#define COMMUNITY_DENY                 0
+#define COMMUNITY_PERMIT               1
+
+/* Number and string based community-list name.  */
+#define COMMUNITY_LIST_STRING          0
+#define COMMUNITY_LIST_NUMBER          1
+
+/* Community-list entry types.  */
+#define COMMUNITY_LIST_STANDARD        0 /* Standard community-list.  */
+#define COMMUNITY_LIST_EXPANDED        1 /* Expanded community-list.  */
+#define COMMUNITY_LIST_AUTO            2 /* Automatically detected.  */
+#define EXTCOMMUNITY_LIST_STANDARD     3 /* Standard extcommunity-list.  */
+#define EXTCOMMUNITY_LIST_EXPANDED     4 /* Expanded extcommunity-list.  */
+#define EXTCOMMUNITY_LIST_AUTO         5 /* Automatically detected.  */
+
+/* Community-list.  */
+struct community_list
+{
+  /* Name of the community-list.  */
+  char *name;
+
+  /* String or number.  */
+  int sort;
+
+  /* Link to upper list.  */
+  struct community_list_list *parent;
+
+  /* Linked list for other community-list.  */
+  struct community_list *next;
+  struct community_list *prev;
+
+  /* Community-list entry in this community-list.  */
+  struct community_entry *head;
+  struct community_entry *tail;
+};
+
+/* Each entry in community-list.  */
+struct community_entry
+{
+  struct community_entry *next;
+  struct community_entry *prev;
+
+  /* Permit or deny.  */
+  u_char direct;
+
+  /* Standard or expanded.  */
+  u_char style;
+
+  /* Any match.  */
+  u_char any;
+
+  /* Community structure.  */
+  union
+  {
+    struct community *com;
+    struct ecommunity *ecom;
+  } u;
+
+  /* Configuration string.  */
+  char *config;
+
+  /* Expanded community-list regular expression.  */
+  regex_t *reg;
+};
+
+/* Linked list of community-list.  */
+struct community_list_list
+{
+  struct community_list *head;
+  struct community_list *tail;
+};
+
+/* Master structure of community-list and extcommunity-list.  */
+struct community_list_master
+{
+  struct community_list_list num;
+  struct community_list_list str;
+};
+
+/* Community-list handler.  community_list_init() returns this
+   structure as handler.  */
+struct community_list_handler
+{
+  /* Community-list.  */
+  struct community_list_master community_list;
+
+  /* Exteded community-list.  */
+  struct community_list_master extcommunity_list;
+};
+
+/* Error code of community-list.  */
+#define COMMUNITY_LIST_ERR_CANT_FIND_LIST        -1
+#define COMMUNITY_LIST_ERR_MALFORMED_VAL         -2
+#define COMMUNITY_LIST_ERR_STANDARD_CONFLICT     -3
+#define COMMUNITY_LIST_ERR_EXPANDED_CONFLICT     -4
+
+/* Handler.  */
+extern struct community_list_handler *bgp_clist;
+
+/* Prototypes.  */
+struct community_list_handler *community_list_init ();
+
+int community_list_set (struct community_list_handler *ch,
+			char *name, char *str, int direct, int style);
+int community_list_unset (struct community_list_handler *ch,
+			  char *name, char *str, int direct, int style);
+int extcommunity_list_set (struct community_list_handler *ch,
+			   char *name, char *str, int direct, int style);
+int extcommunity_list_unset (struct community_list_handler *ch,
+			     char *name, char *str, int direct, int style);
+
+struct community_list_master *
+community_list_master_lookup (struct community_list_handler *, int);
+
+struct community_list *
+community_list_lookup (struct community_list_handler *, char *, int);
+
+int community_list_match (struct community *, struct community_list *);
+int community_list_exact_match (struct community *, struct community_list *);
+struct community *
+community_list_match_delete (struct community *,
+			     struct community_list *);
diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c
new file mode 100644
index 0000000..83b1cc5
--- /dev/null
+++ b/bgpd/bgp_community.c
@@ -0,0 +1,629 @@
+/* Community attribute related functions.
+   Copyright (C) 1998, 2001 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "hash.h"
+#include "memory.h"
+
+#include "bgpd/bgp_community.h"
+
+/* Hash of community attribute. */
+struct hash *comhash;
+
+/* Allocate a new communities value.  */
+struct community *
+community_new ()
+{
+  return (struct community *) XCALLOC (MTYPE_COMMUNITY,
+				       sizeof (struct community));
+}
+
+/* Free communities value.  */
+void
+community_free (struct community *com)
+{
+  if (com->val)
+    XFREE (MTYPE_COMMUNITY_VAL, com->val);
+  if (com->str)
+    XFREE (MTYPE_COMMUNITY_STR, com->str);
+  XFREE (MTYPE_COMMUNITY, com);
+}
+
+/* Add one community value to the community. */
+void
+community_add_val (struct community *com, u_int32_t val)
+{
+  com->size++;
+  if (com->val)
+    com->val = XREALLOC (MTYPE_COMMUNITY_VAL, com->val, com_length (com));
+  else
+    com->val = XMALLOC (MTYPE_COMMUNITY_VAL, com_length (com));
+
+  val = htonl (val);
+  memcpy (com_lastval (com), &val, sizeof (u_int32_t));
+}
+
+/* Delete one community. */
+void
+community_del_val (struct community *com, u_int32_t *val)
+{
+  int i = 0;
+  int c = 0;
+
+  if (! com->val)
+    return;
+
+  while (i < com->size)
+    {
+      if (memcmp (com->val + i, val, sizeof (u_int32_t)) == 0)
+	{
+	  c = com->size -i -1;
+
+	  if (c > 0)
+	    memcpy (com->val + i, com->val + (i + 1), c * sizeof (val));
+
+	  com->size--;
+
+	  if (com->size > 0)
+	    com->val = XREALLOC (MTYPE_COMMUNITY_VAL, com->val,
+				 com_length (com));
+	  else
+	    {
+	      XFREE (MTYPE_COMMUNITY_VAL, com->val);
+	      com->val = NULL;
+	    }
+	  return;
+	}
+      i++;
+    }
+}
+
+/* Delete all communities listed in com2 from com1 */
+struct community *
+community_delete (struct community *com1, struct community *com2)
+{
+  int i = 0;
+
+  while(i < com2->size)
+    {
+      community_del_val (com1, com2->val + i);
+      i++;
+    }
+
+  return com1;
+}
+
+/* Callback function from qsort(). */
+int
+community_compare (const void *a1, const void *a2)
+{
+  u_int32_t v1;
+  u_int32_t v2;
+
+  memcpy (&v1, a1, sizeof (u_int32_t));
+  memcpy (&v2, a2, sizeof (u_int32_t));
+  v1 = ntohl (v1);
+  v2 = ntohl (v2);
+
+  if (v1 < v2)
+    return -1;
+  if (v1 > v2)
+    return 1;
+  return 0;
+}
+
+int
+community_include (struct community *com, u_int32_t val)
+{
+  int i;
+
+  val = htonl (val);
+
+  for (i = 0; i < com->size; i++)
+    if (memcmp (&val, com_nthval (com, i), sizeof (u_int32_t)) == 0)
+      return 1;
+
+  return 0;
+}
+
+u_int32_t
+community_val_get (struct community *com, int i)
+{
+  u_char *p;
+  u_int32_t val;
+
+  p = (u_char *) com->val;
+  p += (i * 4);
+
+  memcpy (&val, p, sizeof (u_int32_t));
+
+  return ntohl (val);
+}
+
+/* Sort and uniq given community. */
+struct community *
+community_uniq_sort (struct community *com)
+{
+  int i;
+  struct community *new;
+  u_int32_t val;
+
+  if (! com)
+    return NULL;
+  
+  new = community_new ();;
+  
+  for (i = 0; i < com->size; i++)
+    {
+      val = community_val_get (com, i);
+
+      if (! community_include (new, val))
+	community_add_val (new, val);
+    }
+
+  qsort (new->val, new->size, sizeof (u_int32_t), community_compare);
+
+  return new;
+}
+
+/* Convert communities attribute to string.
+
+   For Well-known communities value, below keyword is used.
+
+   0x0             "internet"    
+   0xFFFFFF01      "no-export"
+   0xFFFFFF02      "no-advertise"
+   0xFFFFFF03      "local-AS"
+
+   For other values, "AS:VAL" format is used.  */
+static char *
+community_com2str  (struct community *com)
+{
+  int i;
+  char *str;
+  char *pnt;
+  int len;
+  int first;
+  u_int32_t comval;
+  u_int16_t as;
+  u_int16_t val;
+
+  /* When communities attribute is empty.  */
+  if (com->size == 0)
+    {
+      str = XMALLOC (MTYPE_COMMUNITY_STR, 1);
+      str[0] = '\0';
+      return str;
+    }
+
+  /* Memory allocation is time consuming work.  So we calculate
+     required string length first.  */
+  len = 0;
+
+  for (i = 0; i < com->size; i++)
+    {
+      memcpy (&comval, com_nthval (com, i), sizeof (u_int32_t));
+      comval = ntohl (comval);
+
+      switch (comval) 
+	{
+	case COMMUNITY_INTERNET:
+	  len += strlen (" internet");
+	  break;
+	case COMMUNITY_NO_EXPORT:
+	  len += strlen (" no-export");
+	  break;
+	case COMMUNITY_NO_ADVERTISE:
+	  len += strlen (" no-advertise");
+	  break;
+	case COMMUNITY_LOCAL_AS:
+	  len += strlen (" local-AS");
+	  break;
+	default:
+	  len += strlen (" 65536:65535");
+	  break;
+	}
+    }
+
+  /* Allocate memory.  */
+  str = pnt = XMALLOC (MTYPE_COMMUNITY_STR, len);
+  first = 1;
+
+  /* Fill in string.  */
+  for (i = 0; i < com->size; i++)
+    {
+      memcpy (&comval, com_nthval (com, i), sizeof (u_int32_t));
+      comval = ntohl (comval);
+
+      if (first)
+	first = 0;
+      else
+	*pnt++ = ' ';
+
+      switch (comval) 
+	{
+	case COMMUNITY_INTERNET:
+	  strcpy (pnt, "internet");
+	  pnt += strlen ("internet");
+	  break;
+	case COMMUNITY_NO_EXPORT:
+	  strcpy (pnt, "no-export");
+	  pnt += strlen ("no-export");
+	  break;
+	case COMMUNITY_NO_ADVERTISE:
+	  strcpy (pnt, "no-advertise");
+	  pnt += strlen ("no-advertise");
+	  break;
+	case COMMUNITY_LOCAL_AS:
+	  strcpy (pnt, "local-AS");
+	  pnt += strlen ("local-AS");
+	  break;
+	default:
+	  as = (comval >> 16) & 0xFFFF;
+	  val = comval & 0xFFFF;
+	  sprintf (pnt, "%d:%d", as, val);
+	  pnt += strlen (pnt);
+	  break;
+	}
+    }
+  *pnt = '\0';
+
+  return str;
+}
+
+/* Intern communities attribute.  */
+struct community *
+community_intern (struct community *com)
+{
+  struct community *find;
+
+  /* Assert this community structure is not interned. */
+  assert (com->refcnt == 0);
+
+  /* Lookup community hash. */
+  find = (struct community *) hash_get (comhash, com, hash_alloc_intern);
+
+  /* Arguemnt com is allocated temporary.  So when it is not used in
+     hash, it should be freed.  */
+  if (find != com)
+    community_free (com);
+
+  /* Increment refrence counter.  */
+  find->refcnt++;
+
+  /* Make string.  */
+  if (! find->str)
+    find->str = community_com2str (find);
+
+  return find;
+}
+
+/* Free community attribute. */
+void
+community_unintern (struct community *com)
+{
+  struct community *ret;
+
+  if (com->refcnt)
+    com->refcnt--;
+
+  /* Pull off from hash.  */
+  if (com->refcnt == 0)
+    {
+      /* Community value com must exist in hash. */
+      ret = (struct community *) hash_release (comhash, com);
+      assert (ret != NULL);
+
+      community_free (com);
+    }
+}
+
+/* Create new community attribute. */
+struct community *
+community_parse (char *pnt, u_short length)
+{
+  struct community tmp;
+  struct community *new;
+
+  /* If length is malformed return NULL. */
+  if (length % 4)
+    return NULL;
+
+  /* Make temporary community for hash look up. */
+  tmp.size = length / 4;
+  tmp.val = (u_int32_t *) pnt;
+
+  new = community_uniq_sort (&tmp);
+
+  return community_intern (new);
+}
+
+struct community *
+community_dup (struct community *com)
+{
+  struct community *new;
+
+  new = XCALLOC (MTYPE_COMMUNITY, sizeof (struct community));
+  new->size = com->size;
+  if (new->size)
+    {
+      new->val = XMALLOC (MTYPE_COMMUNITY_VAL, com->size * 4);
+      memcpy (new->val, com->val, com->size * 4);
+    }
+  else
+    new->val = NULL;
+  return new;
+}
+
+/* Retrun string representation of communities attribute. */
+char *
+community_str (struct community *com)
+{
+  if (! com->str)
+    com->str = community_com2str (com);
+  return com->str;
+}
+
+/* Make hash value of community attribute. This function is used by
+   hash package.*/
+unsigned int
+community_hash_make (struct community *com)
+{
+  int c;
+  unsigned int key;
+  unsigned char *pnt;
+
+  key = 0;
+  pnt = (unsigned char *)com->val;
+  
+  for(c = 0; c < com->size * 4; c++)
+    key += pnt[c];
+      
+  return key;
+}
+
+int
+community_match (struct community *com1, struct community *com2)
+{
+  int i = 0;
+  int j = 0;
+
+  if (com1 == NULL && com2 == NULL)
+    return 1;
+
+  if (com1 == NULL || com2 == NULL)
+    return 0;
+
+  if (com1->size < com2->size)
+    return 0;
+
+  /* Every community on com2 needs to be on com1 for this to match */
+  while (i < com1->size && j < com2->size)
+    {
+      if (memcmp (com1->val + i, com2->val + j, sizeof (u_int32_t)) == 0)
+	j++;
+      i++;
+    }
+
+  if (j == com2->size)
+    return 1;
+  else
+    return 0;
+}
+
+/* If two aspath have same value then return 1 else return 0. This
+   function is used by hash package. */
+int
+community_cmp (struct community *com1, struct community *com2)
+{
+  if (com1 == NULL && com2 == NULL)
+    return 1;
+  if (com1 == NULL || com2 == NULL)
+    return 0;
+
+  if (com1->size == com2->size)
+    if (memcmp (com1->val, com2->val, com1->size * 4) == 0)
+      return 1;
+  return 0;
+}
+
+/* Add com2 to the end of com1. */
+struct community *
+community_merge (struct community *com1, struct community *com2)
+{
+  if (com1->val)
+    com1->val = XREALLOC (MTYPE_COMMUNITY_VAL, com1->val, 
+			  (com1->size + com2->size) * 4);
+  else
+    com1->val = XMALLOC (MTYPE_COMMUNITY_VAL, (com1->size + com2->size) * 4);
+
+  memcpy (com1->val + com1->size, com2->val, com2->size * 4);
+  com1->size += com2->size;
+
+  return com1;
+}
+
+/* Community token enum. */
+enum community_token
+{
+  community_token_val,
+  community_token_no_export,
+  community_token_no_advertise,
+  community_token_local_as,
+  community_token_unknown
+};
+
+/* Get next community token from string. */
+char *
+community_gettoken (char *buf, enum community_token *token, u_int32_t *val)
+{
+  char *p = buf;
+
+  /* Skip white space. */
+  while (isspace ((int) *p))
+    p++;
+
+  /* Check the end of the line. */
+  if (*p == '\0')
+    return NULL;
+
+  /* Well known community string check. */
+  if (isalpha ((int) *p)) 
+    {
+      if (strncmp (p, "internet", strlen ("internet")) == 0)
+	{
+	  *val = COMMUNITY_INTERNET;
+	  *token = community_token_no_export;
+	  p += strlen ("internet");
+	  return p;
+	}
+      if (strncmp (p, "no-export", strlen ("no-export")) == 0)
+	{
+	  *val = COMMUNITY_NO_EXPORT;
+	  *token = community_token_no_export;
+	  p += strlen ("no-export");
+	  return p;
+	}
+      if (strncmp (p, "no-advertise", strlen ("no-advertise")) == 0)
+	{
+	  *val = COMMUNITY_NO_ADVERTISE;
+	  *token = community_token_no_advertise;
+	  p += strlen ("no-advertise");
+	  return p;
+	}
+      if (strncmp (p, "local-AS", strlen ("local-AS")) == 0)
+	{
+	  *val = COMMUNITY_LOCAL_AS;
+	  *token = community_token_local_as;
+	  p += strlen ("local-AS");
+	  return p;
+	}
+
+      /* Unknown string. */
+      *token = community_token_unknown;
+      return p;
+    }
+
+  /* Community value. */
+  if (isdigit ((int) *p)) 
+    {
+      int separator = 0;
+      int digit = 0;
+      u_int32_t community_low = 0;
+      u_int32_t community_high = 0;
+
+      while (isdigit ((int) *p) || *p == ':') 
+	{
+	  if (*p == ':') 
+	    {
+	      if (separator)
+		{
+		  *token = community_token_unknown;
+		  return p;
+		}
+	      else
+		{
+		  separator = 1;
+		  digit = 0;
+		  community_high = community_low << 16;
+		  community_low = 0;
+		}
+	    }
+	  else 
+	    {
+	      digit = 1;
+	      community_low *= 10;
+	      community_low += (*p - '0');
+	    }
+	  p++;
+	}
+      if (! digit)
+	{
+	  *token = community_token_unknown;
+	  return p;
+	}
+      *val = community_high + community_low;
+      *token = community_token_val;
+      return p;
+    }
+  *token = community_token_unknown;
+  return p;
+}
+
+/* convert string to community structure */
+struct community *
+community_str2com (char *str)
+{
+  struct community *com = NULL;
+  struct community *com_sort = NULL;
+  u_int32_t val;
+  enum community_token token;
+
+  while ((str = community_gettoken (str, &token, &val))) 
+    {
+      switch (token)
+	{
+	case community_token_val:
+	case community_token_no_export:
+	case community_token_no_advertise:
+	case community_token_local_as:
+	  if (com == NULL)
+	    com = community_new();
+	  community_add_val (com, val);
+	  break;
+	case community_token_unknown:
+	default:
+	  if (com)
+	    community_free (com);
+	  return NULL;
+	  break;
+	}
+    }
+  
+  if (! com)
+    return NULL;
+
+  com_sort = community_uniq_sort (com);
+  community_free (com);
+
+  return com_sort;
+}
+
+/* Return communities hash entry count.  */
+unsigned long
+community_count ()
+{
+  return comhash->count;
+}
+
+/* Return communities hash.  */
+struct hash *
+community_hash ()
+{
+  return comhash;
+}
+
+/* Initialize comminity related hash. */
+void
+community_init ()
+{
+  comhash = hash_create (community_hash_make, community_cmp);
+}
diff --git a/bgpd/bgp_community.h b/bgpd/bgp_community.h
new file mode 100644
index 0000000..58b3f9e
--- /dev/null
+++ b/bgpd/bgp_community.h
@@ -0,0 +1,68 @@
+/* Community attribute related functions.
+   Copyright (C) 1998 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+/* Communities attribute.  */
+struct community 
+{
+  /* Reference count of communities value.  */
+  unsigned long refcnt;
+
+  /* Communities value size.  */
+  int size;
+
+  /* Communities value.  */
+  u_int32_t *val;
+
+  /* String of community attribute.  This sring is used by vty output
+     and expanded community-list for regular expression match.  */
+  char *str;
+};
+
+/* Well-known communities value.  */
+#define COMMUNITY_INTERNET              0x0
+#define COMMUNITY_NO_EXPORT             0xFFFFFF01
+#define COMMUNITY_NO_ADVERTISE          0xFFFFFF02
+#define COMMUNITY_NO_EXPORT_SUBCONFED   0xFFFFFF03
+#define COMMUNITY_LOCAL_AS              0xFFFFFF03
+
+/* Macros of community attribute.  */
+#define com_length(X)    ((X)->size * 4)
+#define com_lastval(X)   ((X)->val + (X)->size - 1)
+#define com_nthval(X,n)  ((X)->val + (n))
+
+/* Prototypes of communities attribute functions.  */
+void community_init ();
+void community_free (struct community *);
+struct community *community_uniq_sort (struct community *);
+struct community *community_parse (char *, u_short);
+struct community *community_intern (struct community *);
+void community_unintern (struct community *);
+char *community_str (struct community *);
+unsigned int community_hash_make (struct community *);
+struct community *community_str2com (char *);
+int community_match (struct community *, struct community *);
+int community_cmp (struct community *, struct community *);
+struct community *community_merge (struct community *, struct community *);
+struct community *community_delete (struct community *, struct community *);
+struct community *community_dup (struct community *);
+int community_include (struct community *, u_int32_t);
+void community_del_val (struct community *, u_int32_t *);
+unsigned long community_count ();
+struct hash *community_hash ();
diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c
new file mode 100644
index 0000000..d70105f
--- /dev/null
+++ b/bgpd/bgp_damp.c
@@ -0,0 +1,648 @@
+/* BGP flap dampening
+   Copyright (C) 2001 IP Infusion Inc.
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+#include <math.h>
+
+#include "prefix.h"
+#include "memory.h"
+#include "command.h"
+#include "log.h"
+#include "thread.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_damp.h"
+#include "bgpd/bgp_table.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_attr.h" 
+#include "bgpd/bgp_advertise.h"
+
+/* Global variable to access damping configuration */
+struct bgp_damp_config bgp_damp_cfg;
+struct bgp_damp_config *damp = &bgp_damp_cfg;
+
+/* Utility macro to add and delete BGP dampening information to no
+   used list.  */
+#define BGP_DAMP_LIST_ADD(N,A)  BGP_INFO_ADD(N,A,no_reuse_list)
+#define BGP_DAMP_LIST_DEL(N,A)  BGP_INFO_DEL(N,A,no_reuse_list)
+
+/* Calculate reuse list index by penalty value.  */
+static int
+bgp_reuse_index (int penalty)
+{
+  int i;
+  int index;
+
+  i = (int)(((double) penalty / damp->reuse_limit - 1.0) * damp->scale_factor);
+  
+  if ( i >= damp->reuse_index_size )
+    i = damp->reuse_index_size - 1;
+
+  index = damp->reuse_index[i] - damp->reuse_index[0];
+
+  return (damp->reuse_offset + index) % damp->reuse_list_size;  
+}
+
+/* Add BGP dampening information to reuse list.  */
+static void 
+bgp_reuse_list_add (struct bgp_damp_info *bdi)
+{
+  int index;
+
+  index = bdi->index = bgp_reuse_index (bdi->penalty);
+
+  bdi->prev = NULL;
+  bdi->next = damp->reuse_list[index];
+  if (damp->reuse_list[index])
+    damp->reuse_list[index]->prev = bdi;
+  damp->reuse_list[index] = bdi;
+}
+
+/* Delete BGP dampening information from reuse list.  */
+static void
+bgp_reuse_list_delete (struct bgp_damp_info *bdi)
+{
+  if (bdi->next)
+    bdi->next->prev = bdi->prev;
+  if (bdi->prev)
+    bdi->prev->next = bdi->next;
+  else
+    damp->reuse_list[bdi->index] = bdi->next;
+}   
+
+/* Return decayed penalty value.  */
+int 
+bgp_damp_decay (time_t tdiff, int penalty)
+{
+  int i;
+
+  i = (int) ((double) tdiff / DELTA_T);
+
+  if (i == 0)
+    return penalty; 
+  
+  if (i >= damp->decay_array_size)
+    return 0;
+
+  return (int) (penalty * damp->decay_array[i]);
+}
+
+/* Handler of reuse timer event.  Each route in the current reuse-list
+   is evaluated.  RFC2439 Section 4.8.7.  */
+int
+bgp_reuse_timer (struct thread *t)
+{
+  struct bgp_damp_info *bdi;
+  struct bgp_damp_info *next;
+  time_t t_now, t_diff;
+  struct bgp *bgp;
+  int bgp_process (struct bgp *, struct bgp_node *, afi_t, safi_t);
+
+  damp->t_reuse = NULL;
+  damp->t_reuse =
+    thread_add_timer (master, bgp_reuse_timer, NULL, DELTA_REUSE);
+
+  bgp = bgp_get_default ();
+  if (! bgp)
+    return 0;
+
+  t_now = time (NULL);
+
+  /* 1.  save a pointer to the current zeroth queue head and zero the
+     list head entry.  */
+  bdi = damp->reuse_list[damp->reuse_offset];
+  damp->reuse_list[damp->reuse_offset] = NULL;
+
+  /* 2.  set offset = modulo reuse-list-size ( offset + 1 ), thereby
+     rotating the circular queue of list-heads.  */
+  damp->reuse_offset = (damp->reuse_offset + 1) % damp->reuse_list_size;
+
+  /* 3. if ( the saved list head pointer is non-empty ) */
+  for (; bdi; bdi = next)
+    {
+      next = bdi->next;
+
+      /* Set t-diff = t-now - t-updated.  */
+      t_diff = t_now - bdi->t_updated;
+
+      /* Set figure-of-merit = figure-of-merit * decay-array-ok [t-diff] */
+      bdi->penalty = bgp_damp_decay (t_diff, bdi->penalty);   
+
+      /* Set t-updated = t-now.  */
+      bdi->t_updated = t_now;
+
+      /* if (figure-of-merit < reuse).  */
+      if (bdi->penalty < damp->reuse_limit)
+	{
+	  /* Reuse the route.  */
+	  UNSET_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED);
+	  bdi->suppress_time = 0;
+
+	  if (bdi->lastrecord == BGP_RECORD_UPDATE)
+	    {
+	      UNSET_FLAG (bdi->binfo->flags, BGP_INFO_HISTORY);
+	      bgp_aggregate_increment (bgp, &bdi->rn->p, bdi->binfo,
+				       bdi->afi, bdi->safi);   
+	      bgp_process (bgp, bdi->rn, bdi->afi, bdi->safi);
+	    }
+
+	  if (bdi->penalty <= damp->reuse_limit / 2.0)
+	    bgp_damp_info_free (bdi, 1);
+	  else
+	    BGP_DAMP_LIST_ADD (damp, bdi);
+	}
+      else
+	/* Re-insert into another list (See RFC2439 Section 4.8.6).  */
+	bgp_reuse_list_add (bdi);
+    }
+
+  return 0;
+}
+
+/* A route becomes unreachable (RFC2439 Section 4.8.2).  */
+int
+bgp_damp_withdraw (struct bgp_info *binfo, struct bgp_node *rn,
+		   afi_t afi, safi_t safi, int attr_change)
+{
+  time_t t_now;
+  struct bgp_damp_info *bdi;
+  double last_penalty = 0;
+  
+  t_now = time (NULL);
+
+  /* Processing Unreachable Messages.  */
+  bdi = binfo->damp_info;
+
+  if (bdi == NULL)
+    {
+      /* If there is no previous stability history. */
+
+      /* RFC2439 said:
+	 1. allocate a damping structure.
+         2. set figure-of-merit = 1.
+         3. withdraw the route.  */
+
+      bdi =  XCALLOC (MTYPE_BGP_DAMP_INFO, sizeof (struct bgp_damp_info));
+      bdi->binfo = binfo;
+      bdi->rn = rn;
+      bdi->penalty = (attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY);
+      bdi->flap = 1;
+      bdi->start_time = t_now;
+      bdi->suppress_time = 0;
+      bdi->index = -1;
+      bdi->afi = afi;
+      bdi->safi = safi;
+      binfo->damp_info = bdi;
+      BGP_DAMP_LIST_ADD (damp, bdi);
+    }
+  else
+    {
+      last_penalty = bdi->penalty;
+
+      /* 1. Set t-diff = t-now - t-updated.  */
+      bdi->penalty = 
+	(bgp_damp_decay (t_now - bdi->t_updated, bdi->penalty) 
+	 + (attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY));
+
+      if (bdi->penalty > damp->ceiling)
+	bdi->penalty = damp->ceiling;
+
+      bdi->flap++;
+    }
+  
+  bdi->lastrecord = BGP_RECORD_WITHDRAW;
+  bdi->t_updated = t_now;
+
+  /* Make this route as historical status.  */
+  SET_FLAG (binfo->flags, BGP_INFO_HISTORY);
+
+  /* Remove the route from a reuse list if it is on one.  */
+  if (CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED))
+    {
+      /* If decay rate isn't equal to 0, reinsert brn. */  
+      if (bdi->penalty != last_penalty)
+	{
+	  bgp_reuse_list_delete (bdi);
+	  bgp_reuse_list_add (bdi);  
+	}
+      return BGP_DAMP_SUPPRESSED; 
+    }
+
+  /* If not suppressed before, do annonunce this withdraw and
+     insert into reuse_list.  */
+  if (bdi->penalty >= damp->suppress_value)
+    {
+      SET_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED);
+      bdi->suppress_time = t_now;
+      BGP_DAMP_LIST_DEL (damp, bdi);
+      bgp_reuse_list_add (bdi);
+    }
+
+  return BGP_DAMP_USED;
+}
+
+int
+bgp_damp_update (struct bgp_info *binfo, struct bgp_node *rn, 
+		 afi_t afi, safi_t safi)
+{
+  time_t t_now;
+  struct bgp_damp_info *bdi;
+  int status;
+
+  bdi = binfo->damp_info;
+  if (! bdi)
+    return BGP_DAMP_USED;
+
+  t_now = time (NULL);
+  UNSET_FLAG (binfo->flags, BGP_INFO_HISTORY); 
+
+  bdi->lastrecord = BGP_RECORD_UPDATE;
+  bdi->penalty = bgp_damp_decay (t_now - bdi->t_updated, bdi->penalty);
+
+  if (! CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED)
+      && (bdi->penalty < damp->suppress_value))
+    status = BGP_DAMP_USED;
+  else if (CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED)
+	   && (bdi->penalty < damp->reuse_limit) )
+    {
+      UNSET_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED);
+      bgp_reuse_list_delete (bdi);
+      BGP_DAMP_LIST_ADD (damp, bdi);
+      bdi->suppress_time = 0;
+      status = BGP_DAMP_USED;
+    }
+  else
+    status = BGP_DAMP_SUPPRESSED;  
+
+  if (bdi->penalty > damp->reuse_limit / 2.0)
+    bdi->t_updated = t_now;
+  else
+    bgp_damp_info_free (bdi, 0);
+	
+  return status;
+}
+
+/* Remove dampening information and history route.  */
+int 
+bgp_damp_scan (struct bgp_info *binfo, afi_t afi, safi_t safi)
+{
+  time_t t_now, t_diff;
+  struct bgp_damp_info *bdi;
+
+  t_now = time (NULL);
+  bdi = binfo->damp_info;
+ 
+  if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
+    {
+      t_diff = t_now - bdi->suppress_time;
+
+      if (t_diff >= damp->max_suppress_time)
+        {
+          UNSET_FLAG (binfo->flags, BGP_INFO_DAMPED);
+          bgp_reuse_list_delete (bdi);
+	  BGP_DAMP_LIST_ADD (damp, bdi);
+          bdi->penalty = damp->reuse_limit;
+          bdi->suppress_time = 0;
+          bdi->t_updated = t_now;
+          
+          /* Need to announce UPDATE once this binfo is usable again. */
+          if (bdi->lastrecord == BGP_RECORD_UPDATE)
+            return 1;
+          else
+            return 0;
+        }
+    }
+  else
+    {
+      t_diff = t_now - bdi->t_updated;
+      bdi->penalty = bgp_damp_decay (t_diff, bdi->penalty);
+
+      if (bdi->penalty <= damp->reuse_limit / 2.0)
+        {
+          /* release the bdi, bdi->binfo. */  
+          bgp_damp_info_free (bdi, 1);
+          return 0;
+        }            
+      else
+        bdi->t_updated = t_now;
+    }       
+  return 0;
+}
+
+void
+bgp_damp_info_free (struct bgp_damp_info *bdi, int withdraw)
+{
+  struct bgp_info *binfo;
+  void bgp_info_delete (struct bgp_node *, struct bgp_info *);
+  void bgp_info_free (struct bgp_info *);
+
+  if (! bdi)
+    return;
+
+  binfo = bdi->binfo;
+  binfo->damp_info = NULL;
+
+  if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
+    bgp_reuse_list_delete (bdi);
+  else
+    BGP_DAMP_LIST_DEL (damp, bdi);
+
+  UNSET_FLAG (binfo->flags, BGP_INFO_DAMPED);
+  UNSET_FLAG (binfo->flags, BGP_INFO_HISTORY);
+
+  if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw)
+    {
+      bgp_info_delete (bdi->rn, binfo);
+      bgp_info_free (binfo);
+      bgp_unlock_node (bdi->rn);
+    }
+  XFREE (MTYPE_BGP_DAMP_INFO, bdi);
+}
+
+void
+bgp_damp_parameter_set (int hlife, int reuse, int sup, int maxsup)
+{
+  double reuse_max_ratio;
+  int i;
+  double j;
+	
+  damp->suppress_value = sup;
+  damp->half_life = hlife;
+  damp->reuse_limit = reuse;
+  damp->max_suppress_time = maxsup;
+
+  /* Initialize params per bgp_damp_config. */
+  damp->reuse_index_size = REUSE_ARRAY_SIZE;
+
+  damp->ceiling = (int)(damp->reuse_limit * (pow(2, (double)damp->max_suppress_time/damp->half_life))); 
+
+  /* Decay-array computations */
+  damp->decay_array_size = ceil ((double) damp->max_suppress_time / DELTA_T);
+  damp->decay_array = XMALLOC (MTYPE_BGP_DAMP_ARRAY,
+			       sizeof(double) * (damp->decay_array_size));
+  damp->decay_array[0] = 1.0;
+  damp->decay_array[1] = exp ((1.0/((double)damp->half_life/DELTA_T)) * log(0.5));
+
+  /* Calculate decay values for all possible times */
+  for (i = 2; i < damp->decay_array_size; i++)
+    damp->decay_array[i] = damp->decay_array[i-1] * damp->decay_array[1];
+	
+  /* Reuse-list computations */
+  i = ceil ((double)damp->max_suppress_time / DELTA_REUSE) + 1;
+  if (i > REUSE_LIST_SIZE || i == 0)
+    i = REUSE_LIST_SIZE;
+  damp->reuse_list_size = i; 
+
+  damp->reuse_list = XCALLOC (MTYPE_BGP_DAMP_ARRAY, 
+			      damp->reuse_list_size 
+			      * sizeof (struct bgp_reuse_node *));
+  memset (damp->reuse_list, 0x00, 
+          damp->reuse_list_size * sizeof (struct bgp_reuse_node *));  
+
+  /* Reuse-array computations */
+  damp->reuse_index = XMALLOC (MTYPE_BGP_DAMP_ARRAY, 
+			       sizeof(int) * damp->reuse_index_size);
+  memset (damp->reuse_index, 0x00,
+          damp->reuse_list_size * sizeof (int));
+
+  reuse_max_ratio = (double)damp->ceiling/damp->reuse_limit;
+  j = (exp((double)damp->max_suppress_time/damp->half_life) * log10(2.0));
+  if ( reuse_max_ratio > j && j != 0 )
+    reuse_max_ratio = j;
+
+  damp->scale_factor = (double)damp->reuse_index_size/(reuse_max_ratio - 1);
+
+  for (i = 0; i < damp->reuse_index_size; i++)
+    {
+      damp->reuse_index[i] = 
+	(int)(((double)damp->half_life / DELTA_REUSE)
+	      * log10 (1.0 / (damp->reuse_limit * ( 1.0 + ((double)i/damp->scale_factor)))) / log10(0.5));
+    }
+}
+
+int
+bgp_damp_enable (struct bgp *bgp, afi_t afi, safi_t safi, int half,
+		 int reuse, int suppress, int max)
+{
+  if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
+    {
+      if (damp->half_life == half
+	  && damp->reuse_limit == reuse
+	  && damp->suppress_value == suppress
+	  && damp->max_suppress_time == max)
+	return 0;
+      bgp_damp_disable (bgp, afi, safi);
+    }
+
+  SET_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING);
+  bgp_damp_parameter_set (half, reuse, suppress, max);
+
+  /* Register reuse timer.  */
+  if (! damp->t_reuse)
+    damp->t_reuse = 
+      thread_add_timer (master, bgp_reuse_timer, NULL, DELTA_REUSE);
+
+  return 0;
+}
+
+void
+bgp_damp_config_clean (struct bgp_damp_config *damp)
+{
+  /* Free decay array */
+  XFREE (MTYPE_BGP_DAMP_ARRAY, damp->decay_array);
+
+  /* Free reuse index array */
+  XFREE (MTYPE_BGP_DAMP_ARRAY, damp->reuse_index);
+
+  /* Free reuse list array. */
+  XFREE (MTYPE_BGP_DAMP_ARRAY, damp->reuse_list);
+}
+
+/* Clean all the bgp_damp_info stored in reuse_list. */
+void
+bgp_damp_info_clean ()
+{
+  int i;
+  struct bgp_damp_info *bdi, *next;
+
+  damp->reuse_offset = 0;
+
+  for (i = 0; i < damp->reuse_list_size; i++)
+    {
+      if (! damp->reuse_list[i])
+	continue;
+
+      for (bdi = damp->reuse_list[i]; bdi; bdi = next)
+	{
+	  next = bdi->next;
+	  bgp_damp_info_free (bdi, 1);
+	}
+      damp->reuse_list[i] = NULL;
+    }
+
+  for (bdi = damp->no_reuse_list; bdi; bdi = next)
+    {
+      next = bdi->next;
+      bgp_damp_info_free (bdi, 1);
+    }
+  damp->no_reuse_list = NULL;
+}
+
+int
+bgp_damp_disable (struct bgp *bgp, afi_t afi, safi_t safi)
+{
+  /* Cancel reuse thread. */
+  if (damp->t_reuse )
+    thread_cancel (damp->t_reuse);
+  damp->t_reuse = NULL;
+
+  /* Clean BGP dampening information.  */
+  bgp_damp_info_clean ();
+
+  /* Clear configuration */
+  bgp_damp_config_clean (&bgp_damp_cfg);
+
+  UNSET_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING);
+  return 0;
+}
+
+int
+bgp_config_write_damp (struct vty *vty)
+{
+  if (&bgp_damp_cfg)
+    {
+      if (bgp_damp_cfg.half_life == DEFAULT_HALF_LIFE*60
+	  && bgp_damp_cfg.reuse_limit == DEFAULT_REUSE
+	  && bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS
+	  && bgp_damp_cfg.max_suppress_time == bgp_damp_cfg.half_life*4)
+	vty_out (vty, " bgp dampening%s", VTY_NEWLINE);
+      else if (bgp_damp_cfg.half_life != DEFAULT_HALF_LIFE*60
+	       && bgp_damp_cfg.reuse_limit == DEFAULT_REUSE
+	       && bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS
+	       && bgp_damp_cfg.max_suppress_time == bgp_damp_cfg.half_life*4)
+	vty_out (vty, " bgp dampening %d%s",
+		 bgp_damp_cfg.half_life/60,
+		 VTY_NEWLINE);
+      else
+	vty_out (vty, " bgp dampening %d %d %d %d%s",
+		 bgp_damp_cfg.half_life/60,
+		 bgp_damp_cfg.reuse_limit,
+		 bgp_damp_cfg.suppress_value,
+		 bgp_damp_cfg.max_suppress_time/60,
+		 VTY_NEWLINE);
+      return 1;
+    }
+  return 0;
+}
+
+#define BGP_UPTIME_LEN 25
+
+char *
+bgp_get_reuse_time (int penalty, char *buf, size_t len)
+{
+  time_t reuse_time = 0;
+  struct tm *tm = NULL;
+
+  if (penalty > damp->reuse_limit)
+    {
+      reuse_time = (int) (DELTA_T * ((log((double)damp->reuse_limit/penalty))/(log(damp->decay_array[1])))); 
+
+      if (reuse_time > damp->max_suppress_time)
+	reuse_time = damp->max_suppress_time;
+
+      tm = gmtime (&reuse_time);
+    }
+  else 
+    reuse_time = 0;
+
+  /* Making formatted timer strings. */
+#define ONE_DAY_SECOND 60*60*24
+#define ONE_WEEK_SECOND 60*60*24*7
+  if (reuse_time == 0)
+    snprintf (buf, len, "00:00:00");
+  else if (reuse_time < ONE_DAY_SECOND)
+    snprintf (buf, len, "%02d:%02d:%02d", 
+              tm->tm_hour, tm->tm_min, tm->tm_sec);
+  else if (reuse_time < ONE_WEEK_SECOND)
+    snprintf (buf, len, "%dd%02dh%02dm", 
+              tm->tm_yday, tm->tm_hour, tm->tm_min);
+  else
+    snprintf (buf, len, "%02dw%dd%02dh", 
+              tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); 
+
+  return buf;
+}
+ 
+void
+bgp_damp_info_vty (struct vty *vty, struct bgp_info *binfo)  
+{
+  struct bgp_damp_info *bdi;
+  time_t t_now, t_diff;
+  char timebuf[BGP_UPTIME_LEN];
+  int penalty;
+
+  /* BGP dampening information.  */
+  bdi = binfo->damp_info;
+
+  /* If dampening is not enabled or there is no dampening information,
+     return immediately.  */
+  if (! damp || ! bdi)
+    return;
+
+  /* Calculate new penalty.  */
+  t_now = time (NULL);
+  t_diff = t_now - bdi->t_updated;
+  penalty = bgp_damp_decay (t_diff, bdi->penalty);
+
+  vty_out (vty, "      Dampinfo: penalty %d, flapped %d times in %s",
+           penalty, bdi->flap,
+	   peer_uptime (bdi->start_time, timebuf, BGP_UPTIME_LEN));
+
+  if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)
+      && ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
+    vty_out (vty, ", reuse in %s",
+	     bgp_get_reuse_time (penalty, timebuf, BGP_UPTIME_LEN));
+
+  vty_out (vty, "%s", VTY_NEWLINE);
+}
+
+char *
+bgp_damp_reuse_time_vty (struct vty *vty, struct bgp_info *binfo)
+{
+  struct bgp_damp_info *bdi;
+  time_t t_now, t_diff;
+  char timebuf[BGP_UPTIME_LEN];
+  int penalty;
+
+  /* BGP dampening information.  */
+  bdi = binfo->damp_info;
+
+  /* If dampening is not enabled or there is no dampening information,
+     return immediately.  */
+  if (! damp || ! bdi)
+    return NULL;
+
+  /* Calculate new penalty.  */
+  t_now = time (NULL);
+  t_diff = t_now - bdi->t_updated;
+  penalty = bgp_damp_decay (t_diff, bdi->penalty);
+
+  return  bgp_get_reuse_time (penalty, timebuf, BGP_UPTIME_LEN);
+}
diff --git a/bgpd/bgp_damp.h b/bgpd/bgp_damp.h
new file mode 100644
index 0000000..f3b9bd6
--- /dev/null
+++ b/bgpd/bgp_damp.h
@@ -0,0 +1,141 @@
+/* BGP flap dampening
+   Copyright (C) 2001 IP Infusion Inc.
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+/* Structure maintained on a per-route basis. */
+struct bgp_damp_info
+{
+  /* Doubly linked list.  This information must be linked to
+     reuse_list or no_reuse_list.  */
+  struct bgp_damp_info *next;
+  struct bgp_damp_info *prev;
+
+  /* Figure-of-merit.  */
+  int penalty;
+
+  /* Number of flapping.  */
+  int flap;
+	
+  /* First flap time  */
+  time_t start_time;
+ 
+  /* Last time penalty was updated.  */
+  time_t t_updated;
+
+  /* Time of route start to be suppressed.  */
+  time_t suppress_time;
+
+  /* Back reference to bgp_info. */
+  struct bgp_info *binfo;
+
+  /* Back reference to bgp_node. */
+  struct bgp_node *rn;
+
+  /* Current index in the reuse_list. */
+  int index;
+
+  /* Last time message type. */
+  u_char lastrecord;
+#define BGP_RECORD_UPDATE	1
+#define BGP_RECORD_WITHDRAW	2
+
+  afi_t afi;
+  safi_t safi;
+};
+
+/* Specified parameter set configuration. */
+struct bgp_damp_config
+{
+  /* Value over which routes suppressed.  */
+  int suppress_value;
+
+  /* Value below which suppressed routes reused.  */
+  int reuse_limit;    
+
+  /* Max time a route can be suppressed.  */
+  int max_suppress_time;      
+
+  /* Time during which accumulated penalty reduces by half.  */
+  int half_life; 
+
+  /* Non-configurable parameters but fixed at implementation time.
+   * To change this values, init_bgp_damp() should be modified.
+   */
+  int tmax;		  /* Max time previous instability retained */
+  int reuse_list_size;		/* Number of reuse lists */
+  int reuse_index_size;		/* Size of reuse index array */
+
+  /* Non-configurable parameters.  Most of these are calculated from
+   * the configurable parameters above.
+   */
+  unsigned int ceiling;		/* Max value a penalty can attain */
+  int decay_rate_per_tick;	/* Calculated from half-life */
+  int decay_array_size;		/* Calculated using config parameters */
+  double scale_factor;
+  int reuse_scale_factor; 
+         
+  /* Decay array per-set based. */ 
+  double *decay_array;	
+
+  /* Reuse index array per-set based. */ 
+  int *reuse_index;
+
+  /* Reuse list array per-set based. */  
+  struct bgp_damp_info **reuse_list;
+  int reuse_offset;
+        
+  /* All dampening information which is not on reuse list.  */
+  struct bgp_damp_info *no_reuse_list;
+
+  /* Reuse timer thread per-set base. */
+  struct thread* t_reuse;
+};
+
+#define BGP_DAMP_NONE           0
+#define BGP_DAMP_USED		1
+#define BGP_DAMP_SUPPRESSED	2
+
+/* Time granularity for reuse lists */
+#define DELTA_REUSE	          10
+
+/* Time granularity for decay arrays */
+#define DELTA_T 	           5
+
+#define DEFAULT_PENALTY         1000
+
+#define DEFAULT_HALF_LIFE         15
+#define DEFAULT_REUSE 	       	 750
+#define DEFAULT_SUPPRESS 	2000
+
+#define REUSE_LIST_SIZE          256
+#define REUSE_ARRAY_SIZE        1024
+
+int bgp_damp_enable (struct bgp *, afi_t, safi_t, int, int, int, int);
+int bgp_damp_disable (struct bgp *, afi_t, safi_t);
+int bgp_damp_withdraw (struct bgp_info *, struct bgp_node *,
+		       afi_t, safi_t, int);
+int bgp_damp_update (struct bgp_info *, struct bgp_node *, afi_t, safi_t);
+int bgp_damp_scan (struct bgp_info *, afi_t, safi_t);
+void bgp_damp_info_free (struct bgp_damp_info *, int);
+void bgp_damp_info_clean ();
+char * bgp_get_reuse_time (int, char*, size_t);
+int bgp_damp_decay (time_t, int);
+int bgp_config_write_damp (struct vty *);
+void bgp_damp_info_vty (struct vty *, struct bgp_info *);
+char * bgp_damp_reuse_time_vty (struct vty *, struct bgp_info *);
diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c
new file mode 100644
index 0000000..bb1a610
--- /dev/null
+++ b/bgpd/bgp_debug.c
@@ -0,0 +1,732 @@
+/* BGP-4, BGP-4+ packet debug routine
+   Copyright (C) 1996, 97, 99 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "version.h"
+#include "prefix.h"
+#include "linklist.h"
+#include "stream.h"
+#include "command.h"
+#include "str.h"
+#include "log.h"
+#include "sockunion.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_aspath.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_community.h"
+
+unsigned long conf_bgp_debug_fsm;
+unsigned long conf_bgp_debug_events;
+unsigned long conf_bgp_debug_packet;
+unsigned long conf_bgp_debug_filter;
+unsigned long conf_bgp_debug_keepalive;
+unsigned long conf_bgp_debug_update;
+unsigned long conf_bgp_debug_normal;
+
+unsigned long term_bgp_debug_fsm;
+unsigned long term_bgp_debug_events;
+unsigned long term_bgp_debug_packet;
+unsigned long term_bgp_debug_filter;
+unsigned long term_bgp_debug_keepalive;
+unsigned long term_bgp_debug_update;
+unsigned long term_bgp_debug_normal;
+
+/* messages for BGP-4 status */
+struct message bgp_status_msg[] = 
+{
+  { 0, "null" },
+  { Idle, "Idle" },
+  { Connect, "Connect" },
+  { Active, "Active" },
+  { OpenSent, "OpenSent" },
+  { OpenConfirm, "OpenConfirm" },
+  { Established, "Established" },
+};
+int bgp_status_msg_max = BGP_STATUS_MAX;
+
+/* BGP message type string. */
+char *bgp_type_str[] =
+{
+  NULL,
+  "OPEN",
+  "UPDATE",
+  "NOTIFICATION",
+  "KEEPALIVE",
+  "ROUTE-REFRESH",
+  "CAPABILITY"
+};
+
+/* message for BGP-4 Notify */
+struct message bgp_notify_msg[] = 
+{
+  { 0, "" },
+  { BGP_NOTIFY_HEADER_ERR, "Message Header Error"},
+  { BGP_NOTIFY_OPEN_ERR, "OPEN Message Error"},
+  { BGP_NOTIFY_UPDATE_ERR, "UPDATE Message Error"},
+  { BGP_NOTIFY_HOLD_ERR, "Hold Timer Expired"},
+  { BGP_NOTIFY_FSM_ERR, "Finite State Machine Error"},
+  { BGP_NOTIFY_CEASE, "Cease"},
+  { BGP_NOTIFY_CAPABILITY_ERR, "CAPABILITY Message Error"},
+};
+int bgp_notify_msg_max = BGP_NOTIFY_MAX;
+
+struct message bgp_notify_head_msg[] = 
+{
+  { 0, "null"},
+  { BGP_NOTIFY_HEADER_NOT_SYNC, "/Connection Not Synchronized."},
+  { BGP_NOTIFY_HEADER_BAD_MESLEN, "/Bad Message Length."},
+  { BGP_NOTIFY_HEADER_BAD_MESTYPE, "/Bad Message Type."}
+};
+int bgp_notify_head_msg_max = BGP_NOTIFY_HEADER_MAX;
+
+struct message bgp_notify_open_msg[] = 
+{
+  { 0, "null" },
+  { BGP_NOTIFY_OPEN_UNSUP_VERSION, "/Unsupported Version Number." },
+  { BGP_NOTIFY_OPEN_BAD_PEER_AS, "/Bad Peer AS."},
+  { BGP_NOTIFY_OPEN_BAD_BGP_IDENT, "/Bad BGP Identifier."},
+  { BGP_NOTIFY_OPEN_UNSUP_PARAM, "/Unsupported Optional Parameter."},
+  { BGP_NOTIFY_OPEN_AUTH_FAILURE, "/Authentication Failure."},
+  { BGP_NOTIFY_OPEN_UNACEP_HOLDTIME, "/Unacceptable Hold Time."}, 
+  { BGP_NOTIFY_OPEN_UNSUP_CAPBL, "/Unsupported Capability."},
+};
+int bgp_notify_open_msg_max = BGP_NOTIFY_OPEN_MAX;
+
+struct message bgp_notify_update_msg[] = 
+{
+  { 0, "null"}, 
+  { BGP_NOTIFY_UPDATE_MAL_ATTR, "/Malformed Attribute List."},
+  { BGP_NOTIFY_UPDATE_UNREC_ATTR, "/Unrecognized Well-known Attribute."},
+  { BGP_NOTIFY_UPDATE_MISS_ATTR, "/Missing Well-known Attribute."},
+  { BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, "/Attribute Flags Error."},
+  { BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, "/Attribute Length Error."},
+  { BGP_NOTIFY_UPDATE_INVAL_ORIGIN, "/Invalid ORIGIN Attribute."},
+  { BGP_NOTIFY_UPDATE_AS_ROUTE_LOOP, "/AS Routing Loop."},
+  { BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP, "/Invalid NEXT_HOP Attribute."},
+  { BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, "/Optional Attribute Error."},
+  { BGP_NOTIFY_UPDATE_INVAL_NETWORK, "/Invalid Network Field."},
+  { BGP_NOTIFY_UPDATE_MAL_AS_PATH, "/Malformed AS_PATH."},
+};
+int bgp_notify_update_msg_max = BGP_NOTIFY_UPDATE_MAX;
+
+struct message bgp_notify_cease_msg[] =
+{
+  { 0, ""},
+  { BGP_NOTIFY_CEASE_MAX_PREFIX, "/Maximum Number of Prefixes Reached."},
+  { BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN, "/Administratively Shutdown."},
+  { BGP_NOTIFY_CEASE_PEER_UNCONFIG, "/Peer Unconfigured."},
+  { BGP_NOTIFY_CEASE_ADMIN_RESET, "/Administratively Reset."},
+  { BGP_NOTIFY_CEASE_CONNECT_REJECT, "/Connection Rejected."},
+  { BGP_NOTIFY_CEASE_CONFIG_CHANGE, "/Other Configuration Change."},
+};
+int bgp_notify_cease_msg_max = BGP_NOTIFY_CEASE_MAX;
+
+struct message bgp_notify_capability_msg[] = 
+{
+  { 0, "null" },
+  { BGP_NOTIFY_CAPABILITY_INVALID_ACTION, "/Invalid Action Value." },
+  { BGP_NOTIFY_CAPABILITY_INVALID_LENGTH, "/Invalid Capability Length."},
+  { BGP_NOTIFY_CAPABILITY_MALFORMED_CODE, "/Malformed Capability Value."},
+};
+int bgp_notify_capability_msg_max = BGP_NOTIFY_CAPABILITY_MAX;
+
+/* Origin strings. */
+char *bgp_origin_str[] = {"i","e","?"};
+char *bgp_origin_long_str[] = {"IGP","EGP","incomplete"};
+
+/* Dump attribute. */
+void
+bgp_dump_attr (struct peer *peer, struct attr *attr, char *buf, size_t size)
+{
+
+  if (! attr)
+    return;
+
+  snprintf (buf, size, "nexthop %s", inet_ntoa (attr->nexthop));
+  snprintf (buf + strlen (buf), size - strlen (buf), ", origin %s",
+	    bgp_origin_str[attr->origin]);
+
+#ifdef HAVE_IPV6
+  {
+    char addrbuf[BUFSIZ];
+
+    /* Add MP case. */
+    if (attr->mp_nexthop_len == 16 || attr->mp_nexthop_len == 32)
+      snprintf (buf + strlen (buf), size - strlen (buf), ", mp_nexthop %s",
+		inet_ntop (AF_INET6, &attr->mp_nexthop_global, 
+			   addrbuf, BUFSIZ));
+
+    if (attr->mp_nexthop_len == 32)
+      snprintf (buf + strlen (buf), size - strlen (buf), "(%s)",
+		inet_ntop (AF_INET6, &attr->mp_nexthop_local, 
+			   addrbuf, BUFSIZ));
+  }
+#endif /* HAVE_IPV6 */
+
+  if (peer_sort (peer) == BGP_PEER_IBGP)
+    snprintf (buf + strlen (buf), size - strlen (buf), ", localpref %d",
+	      attr->local_pref);
+
+  if (attr->med)
+    snprintf (buf + strlen (buf), size - strlen (buf), ", metric %d",
+	      attr->med);
+
+  if (attr->community) 
+    snprintf (buf + strlen (buf), size - strlen (buf), ", community %s",
+	      community_str (attr->community));
+
+  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
+    snprintf (buf + strlen (buf), size - strlen (buf), ", atomic-aggregate");
+
+  if (attr->aggregator_as)
+    snprintf (buf + strlen (buf), size - strlen (buf), ", aggregated by %d %s",
+	      attr->aggregator_as, inet_ntoa (attr->aggregator_addr));
+
+  if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID))
+    snprintf (buf + strlen (buf), size - strlen (buf), ", originator %s",
+	      inet_ntoa (attr->originator_id));
+
+  if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST))
+    {
+      int i;
+
+      snprintf (buf + strlen (buf), size - strlen (buf), ", clusterlist ");
+      for (i = 0; i < attr->cluster->length / 4; i++)
+	snprintf (buf + strlen (buf), size - strlen (buf), "%s",
+		  inet_ntoa (attr->cluster->list[i]));
+    }
+
+  if (attr->aspath) 
+    snprintf (buf + strlen (buf), size - strlen (buf), ", path %s",
+	      aspath_print (attr->aspath));
+}
+
+/* dump notify packet */
+void
+bgp_notify_print(struct peer *peer, struct bgp_notify *bgp_notify, char *direct)
+{
+  char *subcode_str;
+
+  subcode_str = "";
+
+  switch (bgp_notify->code) 
+    {
+    case BGP_NOTIFY_HEADER_ERR:
+      subcode_str = LOOKUP (bgp_notify_head_msg, bgp_notify->subcode);
+      break;
+    case BGP_NOTIFY_OPEN_ERR:
+      subcode_str = LOOKUP (bgp_notify_open_msg, bgp_notify->subcode);
+      break;
+    case BGP_NOTIFY_UPDATE_ERR:
+      subcode_str = LOOKUP (bgp_notify_update_msg, bgp_notify->subcode);
+      break;
+    case BGP_NOTIFY_HOLD_ERR:
+      subcode_str = "";
+      break;
+    case BGP_NOTIFY_FSM_ERR:
+      subcode_str = "";
+      break;
+    case BGP_NOTIFY_CEASE:
+      subcode_str = LOOKUP (bgp_notify_cease_msg, bgp_notify->subcode);
+      break;
+    case BGP_NOTIFY_CAPABILITY_ERR:
+      subcode_str = LOOKUP (bgp_notify_capability_msg, bgp_notify->subcode);
+      break;
+    }
+  if (BGP_DEBUG (normal, NORMAL))
+    plog_info (peer->log, "%s %s NOTIFICATION %d/%d (%s%s) %d bytes %s",
+	       peer ? peer->host : "",
+	       direct, bgp_notify->code, bgp_notify->subcode,
+	       LOOKUP (bgp_notify_msg, bgp_notify->code),
+	       subcode_str, bgp_notify->length,
+	       bgp_notify->data ? bgp_notify->data : "");
+}
+
+/* Debug option setting interface. */
+unsigned long bgp_debug_option = 0;
+
+int  
+debug (unsigned int option)
+{
+  return bgp_debug_option & option; 
+}
+
+DEFUN (debug_bgp_fsm,
+       debug_bgp_fsm_cmd,
+       "debug bgp fsm",
+       DEBUG_STR
+       BGP_STR
+       "BGP Finite State Machine\n")
+{
+  if (vty->node == CONFIG_NODE)
+    DEBUG_ON (fsm, FSM);
+  else
+    {
+      TERM_DEBUG_ON (fsm, FSM);
+      vty_out (vty, "BGP fsm debugging is on%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_bgp_fsm,
+       no_debug_bgp_fsm_cmd,
+       "no debug bgp fsm",
+       NO_STR
+       DEBUG_STR
+       BGP_STR
+       "Finite State Machine\n")
+{
+  if (vty->node == CONFIG_NODE)
+    DEBUG_OFF (fsm, FSM);
+  else
+    {
+      TERM_DEBUG_OFF (fsm, FSM);
+      vty_out (vty, "BGP fsm debugging is off%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_debug_bgp_fsm,
+       undebug_bgp_fsm_cmd,
+       "undebug bgp fsm",
+       UNDEBUG_STR
+       DEBUG_STR
+       BGP_STR
+       "Finite State Machine\n")
+
+DEFUN (debug_bgp_events,
+       debug_bgp_events_cmd,
+       "debug bgp events",
+       DEBUG_STR
+       BGP_STR
+       "BGP events\n")
+{
+  if (vty->node == CONFIG_NODE)
+    DEBUG_ON (events, EVENTS);
+  else
+    {
+      TERM_DEBUG_ON (events, EVENTS);
+      vty_out (vty, "BGP events debugging is on%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_bgp_events,
+       no_debug_bgp_events_cmd,
+       "no debug bgp events",
+       NO_STR
+       DEBUG_STR
+       BGP_STR
+       "BGP events\n")
+{
+  if (vty->node == CONFIG_NODE)
+    DEBUG_OFF (events, EVENTS);
+  else
+    {
+      TERM_DEBUG_OFF (events, EVENTS);
+      vty_out (vty, "BGP events debugging is off%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_debug_bgp_events,
+       undebug_bgp_events_cmd,
+       "undebug bgp events",
+       UNDEBUG_STR
+       BGP_STR
+       "BGP events\n")
+
+DEFUN (debug_bgp_filter,
+       debug_bgp_filter_cmd,
+       "debug bgp filters",
+       DEBUG_STR
+       BGP_STR
+       "BGP filters\n")
+{
+  if (vty->node == CONFIG_NODE)
+    DEBUG_ON (filter, FILTER);
+  else
+    {
+      TERM_DEBUG_ON (filter, FILTER);
+      vty_out (vty, "BGP filters debugging is on%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_bgp_filter,
+       no_debug_bgp_filter_cmd,
+       "no debug bgp filters",
+       NO_STR
+       DEBUG_STR
+       BGP_STR
+       "BGP filters\n")
+{
+  if (vty->node == CONFIG_NODE)
+    DEBUG_OFF (filter, FILTER);
+  else
+    {
+      TERM_DEBUG_OFF (filter, FILTER);
+      vty_out (vty, "BGP filters debugging is off%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_debug_bgp_filter,
+       undebug_bgp_filter_cmd,
+       "undebug bgp filters",
+       UNDEBUG_STR
+       BGP_STR
+       "BGP filters\n")
+
+DEFUN (debug_bgp_keepalive,
+       debug_bgp_keepalive_cmd,
+       "debug bgp keepalives",
+       DEBUG_STR
+       BGP_STR
+       "BGP keepalives\n")
+{
+  if (vty->node == CONFIG_NODE)
+    DEBUG_ON (keepalive, KEEPALIVE);
+  else
+    {
+      TERM_DEBUG_ON (keepalive, KEEPALIVE);
+      vty_out (vty, "BGP keepalives debugging is on%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_bgp_keepalive,
+       no_debug_bgp_keepalive_cmd,
+       "no debug bgp keepalives",
+       NO_STR
+       DEBUG_STR
+       BGP_STR
+       "BGP keepalives\n")
+{
+  if (vty->node == CONFIG_NODE)
+    DEBUG_OFF (keepalive, KEEPALIVE);
+  else
+    {
+      TERM_DEBUG_OFF (keepalive, KEEPALIVE);
+      vty_out (vty, "BGP keepalives debugging is off%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_debug_bgp_keepalive,
+       undebug_bgp_keepalive_cmd,
+       "undebug bgp keepalives",
+       UNDEBUG_STR
+       BGP_STR
+       "BGP keepalives\n")
+
+DEFUN (debug_bgp_update,
+       debug_bgp_update_cmd,
+       "debug bgp updates",
+       DEBUG_STR
+       BGP_STR
+       "BGP updates\n")
+{
+  if (vty->node == CONFIG_NODE)
+    {
+      DEBUG_ON (update, UPDATE_IN);
+      DEBUG_ON (update, UPDATE_OUT);
+    }
+  else
+    {
+      TERM_DEBUG_ON (update, UPDATE_IN);
+      TERM_DEBUG_ON (update, UPDATE_OUT);
+      vty_out (vty, "BGP updates debugging is on%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (debug_bgp_update_direct,
+       debug_bgp_update_direct_cmd,
+       "debug bgp updates (in|out)",
+       DEBUG_STR
+       BGP_STR
+       "BGP updates\n"
+       "Inbound updates\n"
+       "Outbound updates\n")
+{
+  if (vty->node == CONFIG_NODE)
+    {
+      if (strncmp ("i", argv[0], 1) == 0)
+	{
+	  DEBUG_OFF (update, UPDATE_OUT);
+	  DEBUG_ON (update, UPDATE_IN);
+	}
+      else
+	{	
+	  DEBUG_OFF (update, UPDATE_IN);
+	  DEBUG_ON (update, UPDATE_OUT);
+	}
+    }
+  else
+    {
+      if (strncmp ("i", argv[0], 1) == 0)
+	{
+	  TERM_DEBUG_OFF (update, UPDATE_OUT);
+	  TERM_DEBUG_ON (update, UPDATE_IN);
+	  vty_out (vty, "BGP updates debugging is on (inbound)%s", VTY_NEWLINE);
+	}
+      else
+	{
+	  TERM_DEBUG_OFF (update, UPDATE_IN);
+	  TERM_DEBUG_ON (update, UPDATE_OUT);
+	  vty_out (vty, "BGP updates debugging is on (outbound)%s", VTY_NEWLINE);
+	}
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_bgp_update,
+       no_debug_bgp_update_cmd,
+       "no debug bgp updates",
+       NO_STR
+       DEBUG_STR
+       BGP_STR
+       "BGP updates\n")
+{
+  if (vty->node == CONFIG_NODE)
+    {
+      DEBUG_OFF (update, UPDATE_IN);
+      DEBUG_OFF (update, UPDATE_OUT);
+    }
+  else
+    {
+      TERM_DEBUG_OFF (update, UPDATE_IN);
+      TERM_DEBUG_OFF (update, UPDATE_OUT);
+      vty_out (vty, "BGP updates debugging is off%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_debug_bgp_update,
+       undebug_bgp_update_cmd,
+       "undebug bgp updates",
+       UNDEBUG_STR
+       BGP_STR
+       "BGP updates\n")
+
+DEFUN (debug_bgp_normal,
+       debug_bgp_normal_cmd,
+       "debug bgp",
+       DEBUG_STR
+       BGP_STR)
+{
+  if (vty->node == CONFIG_NODE)
+    DEBUG_ON (normal, NORMAL);
+  else
+    {
+      TERM_DEBUG_ON (normal, NORMAL);
+      vty_out (vty, "BGP debugging is on%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_bgp_normal,
+       no_debug_bgp_normal_cmd,
+       "no debug bgp",
+       NO_STR
+       DEBUG_STR
+       BGP_STR)
+{
+  if (vty->node == CONFIG_NODE)
+    DEBUG_OFF (normal, NORMAL);
+  else
+    {
+      TERM_DEBUG_OFF (normal, NORMAL);
+      vty_out (vty, "BGP debugging is off%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_debug_bgp_normal,
+       undebug_bgp_normal_cmd,
+       "undebug bgp",
+       UNDEBUG_STR
+       BGP_STR)
+
+DEFUN (no_debug_bgp_all,
+       no_debug_bgp_all_cmd,
+       "no debug all bgp",
+       NO_STR
+       DEBUG_STR
+       "Enable all debugging\n"
+       BGP_STR)
+{
+  TERM_DEBUG_OFF (normal, NORMAL);
+  TERM_DEBUG_OFF (events, EVENTS);
+  TERM_DEBUG_OFF (keepalive, KEEPALIVE);
+  TERM_DEBUG_OFF (update, UPDATE_IN);
+  TERM_DEBUG_OFF (update, UPDATE_OUT);
+  TERM_DEBUG_OFF (fsm, FSM);
+  TERM_DEBUG_OFF (filter, FILTER);
+  vty_out (vty, "All possible debugging has been turned off%s", VTY_NEWLINE);
+      
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_debug_bgp_all,
+       undebug_bgp_all_cmd,
+       "undebug all bgp",
+       UNDEBUG_STR
+       "Enable all debugging\n"
+       BGP_STR)
+
+DEFUN (show_debugging_bgp,
+       show_debugging_bgp_cmd,
+       "show debugging bgp",
+       SHOW_STR
+       DEBUG_STR
+       BGP_STR)
+{
+  vty_out (vty, "BGP debugging status:%s", VTY_NEWLINE);
+
+  if (BGP_DEBUG (normal, NORMAL))
+    vty_out (vty, "  BGP debugging is on%s", VTY_NEWLINE);
+  if (BGP_DEBUG (events, EVENTS))
+    vty_out (vty, "  BGP events debugging is on%s", VTY_NEWLINE);
+  if (BGP_DEBUG (keepalive, KEEPALIVE))
+    vty_out (vty, "  BGP keepalives debugging is on%s", VTY_NEWLINE);
+  if (BGP_DEBUG (update, UPDATE_IN) && BGP_DEBUG (update, UPDATE_OUT))
+    vty_out (vty, "  BGP updates debugging is on%s", VTY_NEWLINE);
+  else if (BGP_DEBUG (update, UPDATE_IN))
+    vty_out (vty, "  BGP updates debugging is on (inbound)%s", VTY_NEWLINE);
+  else if (BGP_DEBUG (update, UPDATE_OUT))
+    vty_out (vty, "  BGP updates debugging is on (outbound)%s", VTY_NEWLINE);
+  if (BGP_DEBUG (fsm, FSM))
+    vty_out (vty, "  BGP fsm debugging is on%s", VTY_NEWLINE);
+  if (BGP_DEBUG (filter, FILTER))
+    vty_out (vty, "  BGP filter debugging is on%s", VTY_NEWLINE);
+  vty_out (vty, "%s", VTY_NEWLINE);
+  return CMD_SUCCESS;
+}
+
+int
+bgp_config_write_debug (struct vty *vty)
+{
+  int write = 0;
+
+  if (CONF_BGP_DEBUG (normal, NORMAL))
+    {
+      vty_out (vty, "debug bgp%s", VTY_NEWLINE);
+      write++;
+    }
+
+  if (CONF_BGP_DEBUG (events, EVENTS))
+    {
+      vty_out (vty, "debug bgp events%s", VTY_NEWLINE);
+      write++;
+    }
+
+  if (CONF_BGP_DEBUG (keepalive, KEEPALIVE))
+    {
+      vty_out (vty, "debug bgp keepalives%s", VTY_NEWLINE);
+      write++;
+    }
+
+  if (CONF_BGP_DEBUG (update, UPDATE_IN) && CONF_BGP_DEBUG (update, UPDATE_OUT))
+    {
+      vty_out (vty, "debug bgp updates%s", VTY_NEWLINE);
+      write++;
+    }
+  else if (CONF_BGP_DEBUG (update, UPDATE_IN))
+    {
+      vty_out (vty, "debug bgp updates in%s", VTY_NEWLINE);
+      write++;
+    }
+  else if (CONF_BGP_DEBUG (update, UPDATE_OUT))
+    {
+      vty_out (vty, "debug bgp updates out%s", VTY_NEWLINE);
+      write++;
+    }
+
+  if (CONF_BGP_DEBUG (fsm, FSM))
+    {
+      vty_out (vty, "debug bgp fsm%s", VTY_NEWLINE);
+      write++;
+    }
+
+  if (CONF_BGP_DEBUG (filter, FILTER))
+    {
+      vty_out (vty, "debug bgp filters%s", VTY_NEWLINE);
+      write++;
+    }
+
+  return write;
+}
+
+struct cmd_node debug_node =
+{
+  DEBUG_NODE,
+  "",
+  1
+};
+
+void
+bgp_debug_init ()
+{
+  install_node (&debug_node, bgp_config_write_debug);
+
+  install_element (ENABLE_NODE, &show_debugging_bgp_cmd);
+
+  install_element (ENABLE_NODE, &debug_bgp_fsm_cmd);
+  install_element (CONFIG_NODE, &debug_bgp_fsm_cmd);
+  install_element (ENABLE_NODE, &debug_bgp_events_cmd);
+  install_element (CONFIG_NODE, &debug_bgp_events_cmd);
+  install_element (ENABLE_NODE, &debug_bgp_filter_cmd);
+  install_element (CONFIG_NODE, &debug_bgp_filter_cmd);
+  install_element (ENABLE_NODE, &debug_bgp_keepalive_cmd);
+  install_element (CONFIG_NODE, &debug_bgp_keepalive_cmd);
+  install_element (ENABLE_NODE, &debug_bgp_update_cmd);
+  install_element (CONFIG_NODE, &debug_bgp_update_cmd);
+  install_element (ENABLE_NODE, &debug_bgp_update_direct_cmd);
+  install_element (CONFIG_NODE, &debug_bgp_update_direct_cmd);
+  install_element (ENABLE_NODE, &debug_bgp_normal_cmd);
+  install_element (CONFIG_NODE, &debug_bgp_normal_cmd);
+
+  install_element (ENABLE_NODE, &no_debug_bgp_fsm_cmd);
+  install_element (ENABLE_NODE, &undebug_bgp_fsm_cmd);
+  install_element (CONFIG_NODE, &no_debug_bgp_fsm_cmd);
+  install_element (ENABLE_NODE, &no_debug_bgp_events_cmd);
+  install_element (ENABLE_NODE, &undebug_bgp_events_cmd);
+  install_element (CONFIG_NODE, &no_debug_bgp_events_cmd);
+  install_element (ENABLE_NODE, &no_debug_bgp_filter_cmd);
+  install_element (ENABLE_NODE, &undebug_bgp_filter_cmd);
+  install_element (CONFIG_NODE, &no_debug_bgp_filter_cmd);
+  install_element (ENABLE_NODE, &no_debug_bgp_keepalive_cmd);
+  install_element (ENABLE_NODE, &undebug_bgp_keepalive_cmd);
+  install_element (CONFIG_NODE, &no_debug_bgp_keepalive_cmd);
+  install_element (ENABLE_NODE, &no_debug_bgp_update_cmd);
+  install_element (ENABLE_NODE, &undebug_bgp_update_cmd);
+  install_element (CONFIG_NODE, &no_debug_bgp_update_cmd);
+  install_element (ENABLE_NODE, &no_debug_bgp_normal_cmd);
+  install_element (ENABLE_NODE, &undebug_bgp_normal_cmd);
+  install_element (CONFIG_NODE, &no_debug_bgp_normal_cmd);
+  install_element (ENABLE_NODE, &no_debug_bgp_all_cmd);
+  install_element (ENABLE_NODE, &undebug_bgp_all_cmd);
+}
diff --git a/bgpd/bgp_debug.h b/bgpd/bgp_debug.h
new file mode 100644
index 0000000..06ba075
--- /dev/null
+++ b/bgpd/bgp_debug.h
@@ -0,0 +1,113 @@
+/* BGP message debug header.
+   Copyright (C) 1996, 97, 98 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+/* sort of packet direction */
+#define DUMP_ON        1
+#define DUMP_SEND      2
+#define DUMP_RECV      4
+
+/* for dump_update */
+#define DUMP_WITHDRAW  8
+#define DUMP_NLRI     16
+
+/* dump detail */
+#define DUMP_DETAIL   32
+
+extern int dump_open;
+extern int dump_update;
+extern int dump_keepalive;
+extern int dump_notify;
+
+extern int Debug_Event;
+extern int Debug_Keepalive;
+extern int Debug_Update;
+extern int Debug_Radix;
+
+#define	NLRI	 1
+#define	WITHDRAW 2
+#define	NO_OPT	 3
+#define	SEND	 4
+#define	RECV	 5
+#define	DETAIL	 6
+
+/* Prototypes. */
+void bgp_debug_init ();
+void bgp_packet_dump (struct stream *);
+
+int debug (unsigned int option);
+
+extern unsigned long conf_bgp_debug_fsm;
+extern unsigned long conf_bgp_debug_events;
+extern unsigned long conf_bgp_debug_packet;
+extern unsigned long conf_bgp_debug_filter;
+extern unsigned long conf_bgp_debug_keepalive;
+extern unsigned long conf_bgp_debug_update;
+extern unsigned long conf_bgp_debug_normal;
+
+extern unsigned long term_bgp_debug_fsm;
+extern unsigned long term_bgp_debug_events;
+extern unsigned long term_bgp_debug_packet;
+extern unsigned long term_bgp_debug_filter;
+extern unsigned long term_bgp_debug_keepalive;
+extern unsigned long term_bgp_debug_update;
+extern unsigned long term_bgp_debug_normal;
+
+#define BGP_DEBUG_FSM                 0x01
+#define BGP_DEBUG_EVENTS              0x01
+#define BGP_DEBUG_PACKET              0x01
+#define BGP_DEBUG_FILTER              0x01
+#define BGP_DEBUG_KEEPALIVE           0x01
+#define BGP_DEBUG_UPDATE_IN           0x01
+#define BGP_DEBUG_UPDATE_OUT          0x02
+#define BGP_DEBUG_NORMAL              0x01
+
+#define BGP_DEBUG_PACKET_SEND         0x01
+#define BGP_DEBUG_PACKET_SEND_DETAIL  0x02
+
+#define BGP_DEBUG_PACKET_RECV         0x01
+#define BGP_DEBUG_PACKET_RECV_DETAIL  0x02
+
+#define CONF_DEBUG_ON(a, b)	(conf_bgp_debug_ ## a |= (BGP_DEBUG_ ## b))
+#define CONF_DEBUG_OFF(a, b)	(conf_bgp_debug_ ## a &= ~(BGP_DEBUG_ ## b))
+
+#define TERM_DEBUG_ON(a, b)	(term_bgp_debug_ ## a |= (BGP_DEBUG_ ## b))
+#define TERM_DEBUG_OFF(a, b)	(term_bgp_debug_ ## a &= ~(BGP_DEBUG_ ## b))
+
+#define DEBUG_ON(a, b) \
+    do { \
+	CONF_DEBUG_ON(a, b); \
+	TERM_DEBUG_ON(a, b); \
+    } while (0)
+#define DEBUG_OFF(a, b) \
+    do { \
+	CONF_DEBUG_OFF(a, b); \
+	TERM_DEBUG_OFF(a, b); \
+    } while (0)
+
+#define BGP_DEBUG(a, b)		(term_bgp_debug_ ## a & BGP_DEBUG_ ## b)
+#define CONF_BGP_DEBUG(a, b)    (conf_bgp_debug_ ## a & BGP_DEBUG_ ## b)
+
+extern char *bgp_type_str[];
+
+void bgp_dump_attr (struct peer *, struct attr *, char *, size_t);
+void bgp_notify_print (struct peer *, struct bgp_notify *, char *);
+
+extern struct message bgp_status_msg[];
+extern int bgp_status_msg_max;
diff --git a/bgpd/bgp_dump.c b/bgpd/bgp_dump.c
new file mode 100644
index 0000000..fca51ed
--- /dev/null
+++ b/bgpd/bgp_dump.c
@@ -0,0 +1,741 @@
+/* BGP-4 dump routine
+   Copyright (C) 1999 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "log.h"
+#include "stream.h"
+#include "sockunion.h"
+#include "command.h"
+#include "prefix.h"
+#include "thread.h"
+#include "bgpd/bgp_table.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_dump.h"
+
+enum bgp_dump_type
+{
+  BGP_DUMP_ALL,
+  BGP_DUMP_UPDATES,
+  BGP_DUMP_ROUTES
+};
+
+enum MRT_MSG_TYPES {
+   MSG_NULL,
+   MSG_START,                   /* sender is starting up */
+   MSG_DIE,                     /* receiver should shut down */
+   MSG_I_AM_DEAD,               /* sender is shutting down */
+   MSG_PEER_DOWN,               /* sender's peer is down */
+   MSG_PROTOCOL_BGP,            /* msg is a BGP packet */
+   MSG_PROTOCOL_RIP,            /* msg is a RIP packet */
+   MSG_PROTOCOL_IDRP,           /* msg is an IDRP packet */
+   MSG_PROTOCOL_RIPNG,          /* msg is a RIPNG packet */
+   MSG_PROTOCOL_BGP4PLUS,       /* msg is a BGP4+ packet */
+   MSG_PROTOCOL_BGP4PLUS_01,    /* msg is a BGP4+ (draft 01) packet */
+   MSG_PROTOCOL_OSPF,           /* msg is an OSPF packet */
+   MSG_TABLE_DUMP               /* routing table dump */
+};
+
+struct bgp_dump
+{
+  enum bgp_dump_type type;
+
+  char *filename;
+
+  FILE *fp;
+
+  unsigned int interval;
+
+  char *interval_str;
+
+  struct thread *t_interval;
+};
+
+/* BGP packet dump output buffer. */
+struct stream *bgp_dump_obuf;
+
+/* BGP dump strucuture for 'dump bgp all' */
+struct bgp_dump bgp_dump_all;
+
+/* BGP dump structure for 'dump bgp updates' */
+struct bgp_dump bgp_dump_updates;
+
+/* BGP dump structure for 'dump bgp routes' */
+struct bgp_dump bgp_dump_routes;
+
+/* Dump whole BGP table is very heavy process.  */
+struct thread *t_bgp_dump_routes;
+
+/* Some define for BGP packet dump. */
+FILE *
+bgp_dump_open_file (struct bgp_dump *bgp_dump)
+{
+  int ret;
+  time_t clock;
+  struct tm *tm;
+  char fullpath[MAXPATHLEN];
+  char realpath[MAXPATHLEN];
+
+  time (&clock);
+  tm = localtime (&clock);
+
+  if (bgp_dump->filename[0] != DIRECTORY_SEP)
+    {
+      sprintf (fullpath, "%s/%s", vty_get_cwd (), bgp_dump->filename);
+      ret = strftime (realpath, MAXPATHLEN, fullpath, tm);
+    }
+  else
+    ret = strftime (realpath, MAXPATHLEN, bgp_dump->filename, tm);
+
+  if (ret == 0)
+    {
+      zlog_warn ("bgp_dump_open_file: strftime error");
+      return NULL;
+    }
+
+  if (bgp_dump->fp)
+    fclose (bgp_dump->fp);
+
+
+  bgp_dump->fp = fopen (realpath, "w");
+
+  if (bgp_dump->fp == NULL)
+    return NULL;
+
+  return bgp_dump->fp;
+}
+
+int
+bgp_dump_interval_add (struct bgp_dump *bgp_dump, int interval)
+{
+  int bgp_dump_interval_func (struct thread *);
+
+  bgp_dump->t_interval = thread_add_timer (master, bgp_dump_interval_func, 
+					   bgp_dump, interval);
+  return 0;
+}
+
+/* Dump common header. */
+void
+bgp_dump_header (struct stream *obuf, int type, int subtype)
+{
+  time_t now;
+
+  /* Set header. */
+  time (&now);
+
+  /* Put dump packet header. */
+  stream_putl (obuf, now);	
+  stream_putw (obuf, type);
+  stream_putw (obuf, subtype);
+
+  stream_putl (obuf, 0);	/* len */
+}
+
+void
+bgp_dump_set_size (struct stream *s, int type)
+{
+  stream_putl_at (s, 8, stream_get_putp (s) - BGP_DUMP_HEADER_SIZE);
+}
+
+void
+bgp_dump_routes_entry (struct prefix *p, struct bgp_info *info, int afi,
+		       int type, unsigned int seq)
+{
+  struct stream *obuf;
+  struct attr *attr;
+  struct peer *peer;
+  int plen;
+  int safi = 0;
+
+  /* Make dump stream. */
+  obuf = bgp_dump_obuf;
+  stream_reset (obuf);
+
+  attr = info->attr;
+  peer = info->peer;
+
+  /* We support MRT's old format. */
+  if (type == MSG_TABLE_DUMP)
+    {
+      bgp_dump_header (obuf, MSG_TABLE_DUMP, afi);
+      stream_putw (obuf, 0);	/* View # */
+      stream_putw (obuf, seq);	/* Sequence number. */
+    }
+  else
+    {
+      bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_ENTRY);
+      
+      stream_putl (obuf, info->uptime); /* Time Last Change */
+      stream_putw (obuf, afi);	/* Address Family */
+      stream_putc (obuf, safi);	/* SAFI */
+    }
+
+  if (afi == AFI_IP)
+    {
+      if (type == MSG_TABLE_DUMP)
+	{
+	  /* Prefix */
+	  stream_put_in_addr (obuf, &p->u.prefix4);
+	  stream_putc (obuf, p->prefixlen);
+
+	  /* Status */
+	  stream_putc (obuf, 1);
+
+	  /* Originated */
+	  stream_putl (obuf, info->uptime);
+
+	  /* Peer's IP address */
+	  stream_put_in_addr (obuf, &peer->su.sin.sin_addr);
+
+	  /* Peer's AS number. */
+	  stream_putw (obuf, peer->as);
+
+	  /* Dump attribute. */
+	  bgp_dump_routes_attr (obuf, attr);
+	}
+      else
+	{
+	  /* Next-Hop-Len */
+	  stream_putc (obuf, IPV4_MAX_BYTELEN);
+	  stream_put_in_addr (obuf, &attr->nexthop);
+	  stream_putc (obuf, p->prefixlen);
+	  plen = PSIZE (p->prefixlen);
+	  stream_put (obuf, &p->u.prefix4, plen);
+	  bgp_dump_routes_attr (obuf, attr);
+	}
+    }
+#ifdef HAVE_IPV6
+  else if (afi == AFI_IP6)
+    {
+      if (type == MSG_TABLE_DUMP)
+	{
+	  /* Prefix */
+	  stream_write (obuf, (u_char *)&p->u.prefix6, IPV6_MAX_BYTELEN);
+	  stream_putc (obuf, p->prefixlen);
+
+	  /* Status */
+	  stream_putc (obuf, 1);
+
+	  /* Originated */
+	  stream_putl (obuf, info->uptime);
+
+	  /* Peer's IP address */
+	  stream_write (obuf, (u_char *)&peer->su.sin6.sin6_addr,
+			IPV6_MAX_BYTELEN);
+
+	  /* Peer's AS number. */
+	  stream_putw (obuf, peer->as);
+
+	  /* Dump attribute. */
+	  bgp_dump_routes_attr (obuf, attr);
+	}
+      else
+	{
+	  ;
+	}
+    }
+#endif /* HAVE_IPV6 */
+
+  /* Set length. */
+  bgp_dump_set_size (obuf, type);
+
+  fwrite (STREAM_DATA (obuf), stream_get_putp (obuf), 1, bgp_dump_routes.fp);
+  fflush (bgp_dump_routes.fp);
+}
+
+/* Runs under child process. */
+void
+bgp_dump_routes_func (int afi)
+{
+  struct stream *obuf;
+  struct bgp_node *rn;
+  struct bgp_info *info;
+  struct bgp *bgp;
+  struct bgp_table *table;
+  unsigned int seq = 0;
+
+  obuf = bgp_dump_obuf;
+
+  bgp = bgp_get_default ();
+  if (!bgp)
+    return;
+
+  if (bgp_dump_routes.fp == NULL)
+    return;
+
+  /* Walk down each BGP route. */
+  table = bgp->rib[afi][SAFI_UNICAST];
+
+  for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
+    for (info = rn->info; info; info = info->next)
+      bgp_dump_routes_entry (&rn->p, info, afi, MSG_TABLE_DUMP, seq++);
+}
+
+int
+bgp_dump_interval_func (struct thread *t)
+{
+  struct bgp_dump *bgp_dump;
+
+  bgp_dump = THREAD_ARG (t);
+  bgp_dump->t_interval = NULL;
+
+  if (bgp_dump_open_file (bgp_dump) == NULL)
+    return 0;
+
+  /* In case of bgp_dump_routes, we need special route dump function. */
+  if (bgp_dump->type == BGP_DUMP_ROUTES)
+    {
+      bgp_dump_routes_func (AFI_IP);
+      bgp_dump_routes_func (AFI_IP6);
+    }
+
+  bgp_dump_interval_add (bgp_dump, bgp_dump->interval);
+  
+  return 0;
+}
+
+/* Dump common information. */
+void
+bgp_dump_common (struct stream *obuf, struct peer *peer)
+{
+  char empty[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+  /* Source AS number and Destination AS number. */
+  stream_putw (obuf, peer->as);
+  stream_putw (obuf, peer->local_as);
+
+  if (peer->afc[AFI_IP][SAFI_UNICAST])
+    {
+      stream_putw (obuf, peer->ifindex);
+      stream_putw (obuf, AFI_IP);
+
+      stream_put (obuf, &peer->su.sin.sin_addr, IPV4_MAX_BYTELEN);
+
+      if (peer->su_local)
+	stream_put (obuf, &peer->su_local->sin.sin_addr, IPV4_MAX_BYTELEN);
+      else
+	stream_put (obuf, empty, IPV4_MAX_BYTELEN);
+    }
+#ifdef HAVE_IPV6
+  else if (peer->afc[AFI_IP6][SAFI_UNICAST])
+    {
+      /* Interface Index and Address family. */
+      stream_putw (obuf, peer->ifindex);
+      stream_putw (obuf, AFI_IP6);
+
+      /* Source IP Address and Destination IP Address. */
+      stream_put (obuf, &peer->su.sin6.sin6_addr, IPV6_MAX_BYTELEN);
+
+      if (peer->su_local)
+	stream_put (obuf, &peer->su_local->sin6.sin6_addr, IPV6_MAX_BYTELEN);
+      else
+	stream_put (obuf, empty, IPV6_MAX_BYTELEN);
+    }
+#endif /* HAVE_IPV6 */
+}
+
+/* Dump BGP status change. */
+void
+bgp_dump_state (struct peer *peer, int status_old, int status_new)
+{
+  struct stream *obuf;
+
+  /* If dump file pointer is disabled return immediately. */
+  if (bgp_dump_all.fp == NULL)
+    return;
+
+  /* Make dump stream. */
+  obuf = bgp_dump_obuf;
+  stream_reset (obuf);
+
+  bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE);
+  bgp_dump_common (obuf, peer);
+
+  stream_putw (obuf, status_old);
+  stream_putw (obuf, status_new);
+
+  /* Set length. */
+  bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP);
+
+  /* Write to the stream. */
+  fwrite (STREAM_DATA (obuf), stream_get_putp (obuf), 1, bgp_dump_all.fp);
+  fflush (bgp_dump_all.fp);
+}
+
+void
+bgp_dump_packet_func (struct bgp_dump *bgp_dump, struct peer *peer,
+		      struct stream *packet)
+{
+  struct stream *obuf;
+
+  /* If dump file pointer is disabled return immediately. */
+  if (bgp_dump->fp == NULL)
+    return;
+
+  /* Make dump stream. */
+  obuf = bgp_dump_obuf;
+  stream_reset (obuf);
+
+  /* Dump header and common part. */
+  bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE);
+  bgp_dump_common (obuf, peer);
+
+  /* Packet contents. */
+  stream_put (obuf, STREAM_DATA (packet), stream_get_endp (packet));
+  
+  /* Set length. */
+  bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP);
+
+  /* Write to the stream. */
+  fwrite (STREAM_DATA (obuf), stream_get_putp (obuf), 1, bgp_dump->fp);
+  fflush (bgp_dump->fp);
+}
+
+/* Called from bgp_packet.c when BGP packet is received. */
+void
+bgp_dump_packet (struct peer *peer, int type, struct stream *packet)
+{
+  /* bgp_dump_all. */
+  bgp_dump_packet_func (&bgp_dump_all, peer, packet);
+
+  /* bgp_dump_updates. */
+  if (type == BGP_MSG_UPDATE)
+    bgp_dump_packet_func (&bgp_dump_updates, peer, packet);
+}
+
+unsigned int
+bgp_dump_parse_time (char *str)
+{
+  int i;
+  int len;
+  int seen_h;
+  int seen_m;
+  int time;
+  unsigned int total;
+
+  time = 0;
+  total = 0;
+  seen_h = 0;
+  seen_m = 0;
+  len = strlen (str);
+
+  for (i = 0; i < len; i++)
+    {
+      if (isdigit ((int) str[i]))
+	{
+	  time *= 10;
+	  time += str[i] - '0';
+	}
+      else if (str[i] == 'H' || str[i] == 'h')
+	{
+	  if (seen_h)
+	    return 0;
+	  if (seen_m)
+	    return 0;
+	  total += time * 60 *60;
+	  time = 0;
+	  seen_h = 1;
+	}
+      else if (str[i] == 'M' || str[i] == 'm')
+	{
+	  if (seen_m)
+	    return 0;
+	  total += time * 60;
+	  time = 0;
+	  seen_h = 1;
+	}
+      else
+	return 0;
+    }
+  return total + time;
+}
+
+int
+bgp_dump_set (struct vty *vty, struct bgp_dump *bgp_dump, int type,
+	      char *path, char *interval_str)
+{
+  if (interval_str)
+    {
+      unsigned int interval;
+
+      /* Check interval string. */
+      interval = bgp_dump_parse_time (interval_str);
+      if (interval == 0)
+	{
+	  vty_out (vty, "Malformed interval string%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	}
+      /* Set interval. */
+      bgp_dump->interval = interval;
+      if (bgp_dump->interval_str)
+	free (bgp_dump->interval_str);
+      bgp_dump->interval_str = strdup (interval_str);
+
+      /* Create interval thread. */
+      bgp_dump_interval_add (bgp_dump, interval);
+    }
+
+  /* Set type. */
+  bgp_dump->type = type;
+
+  /* Set file name. */
+  if (bgp_dump->filename)
+    free (bgp_dump->filename);
+  bgp_dump->filename = strdup (path);
+
+  /* This should be called when interval is expired. */
+  bgp_dump_open_file (bgp_dump);
+
+  return CMD_SUCCESS;
+}
+
+int
+bgp_dump_unset (struct vty *vty, struct bgp_dump *bgp_dump)
+{
+  /* Set file name. */
+  if (bgp_dump->filename)
+    {
+      free (bgp_dump->filename);
+      bgp_dump->filename = NULL;
+    }
+
+  /* This should be called when interval is expired. */
+  if (bgp_dump->fp)
+    {
+      fclose (bgp_dump->fp);
+      bgp_dump->fp = NULL;
+    }
+
+  /* Create interval thread. */
+  if (bgp_dump->t_interval)
+    {
+      thread_cancel (bgp_dump->t_interval);
+      bgp_dump->t_interval = NULL;
+    }
+
+  bgp_dump->interval = 0;
+
+  if (bgp_dump->interval_str)
+    {
+      free (bgp_dump->interval_str);
+      bgp_dump->interval_str = NULL;
+    }
+  
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (dump_bgp_all,
+       dump_bgp_all_cmd,
+       "dump bgp all PATH",
+       "Dump packet\n"
+       "BGP packet dump\n"
+       "Dump all BGP packets\n"
+       "Output filename\n")
+{
+  return bgp_dump_set (vty, &bgp_dump_all, BGP_DUMP_ALL, argv[0], NULL);
+}
+
+DEFUN (dump_bgp_all_interval,
+       dump_bgp_all_interval_cmd,
+       "dump bgp all PATH INTERVAL",
+       "Dump packet\n"
+       "BGP packet dump\n"
+       "Dump all BGP packets\n"
+       "Output filename\n"
+       "Interval of output\n")
+{
+  return bgp_dump_set (vty, &bgp_dump_all, BGP_DUMP_ALL, argv[0], argv[1]);
+}
+
+DEFUN (no_dump_bgp_all,
+       no_dump_bgp_all_cmd,
+       "no dump bgp all [PATH] [INTERVAL]",
+       NO_STR
+       "Dump packet\n"
+       "BGP packet dump\n"
+       "Dump all BGP packets\n")
+{
+  return bgp_dump_unset (vty, &bgp_dump_all);
+}
+
+DEFUN (dump_bgp_updates,
+       dump_bgp_updates_cmd,
+       "dump bgp updates PATH",
+       "Dump packet\n"
+       "BGP packet dump\n"
+       "Dump BGP updates only\n"
+       "Output filename\n")
+{
+  return bgp_dump_set (vty, &bgp_dump_updates, BGP_DUMP_UPDATES, argv[0], NULL);
+}
+
+DEFUN (dump_bgp_updates_interval,
+       dump_bgp_updates_interval_cmd,
+       "dump bgp updates PATH INTERVAL",
+       "Dump packet\n"
+       "BGP packet dump\n"
+       "Dump BGP updates only\n"
+       "Output filename\n"
+       "Interval of output\n")
+{
+  return bgp_dump_set (vty, &bgp_dump_updates, BGP_DUMP_UPDATES, argv[0], argv[1]);
+}
+
+DEFUN (no_dump_bgp_updates,
+       no_dump_bgp_updates_cmd,
+       "no dump bgp updates [PATH] [INTERVAL]",
+       NO_STR
+       "Dump packet\n"
+       "BGP packet dump\n"
+       "Dump BGP updates only\n")
+{
+  return bgp_dump_unset (vty, &bgp_dump_updates);
+}
+
+DEFUN (dump_bgp_routes,
+       dump_bgp_routes_cmd,
+       "dump bgp routes-mrt PATH",
+       "Dump packet\n"
+       "BGP packet dump\n"
+       "Dump whole BGP routing table\n"
+       "Output filename\n")
+{
+  return bgp_dump_set (vty, &bgp_dump_routes, BGP_DUMP_ROUTES, argv[0], NULL);
+}
+
+DEFUN (dump_bgp_routes_interval,
+       dump_bgp_routes_interval_cmd,
+       "dump bgp routes-mrt PATH INTERVAL",
+       "Dump packet\n"
+       "BGP packet dump\n"
+       "Dump whole BGP routing table\n"
+       "Output filename\n"
+       "Interval of output\n")
+{
+  return bgp_dump_set (vty, &bgp_dump_routes, BGP_DUMP_ROUTES, argv[0], argv[1]);
+}
+
+DEFUN (no_dump_bgp_routes,
+       no_dump_bgp_routes_cmd,
+       "no dump bgp routes-mrt [PATH] [INTERVAL]",
+       NO_STR
+       "Dump packet\n"
+       "BGP packet dump\n"
+       "Dump whole BGP routing table\n")
+{
+  return bgp_dump_unset (vty, &bgp_dump_routes);
+}
+
+/* BGP node structure. */
+struct cmd_node bgp_dump_node =
+{
+  DUMP_NODE,
+  "",
+};
+
+#if 0
+char *
+config_time2str (unsigned int interval)
+{
+  static char buf[BUFSIZ];
+
+  buf[0] = '\0';
+
+  if (interval / 3600)
+    {
+      sprintf (buf, "%dh", interval / 3600);
+      interval %= 3600;
+    }
+  if (interval / 60)
+    {
+      sprintf (buf + strlen (buf), "%dm", interval /60);
+      interval %= 60;
+    }
+  if (interval)
+    {
+      sprintf (buf + strlen (buf), "%d", interval);
+    }
+  return buf;
+}
+#endif
+
+int
+config_write_bgp_dump (struct vty *vty)
+{
+  if (bgp_dump_all.filename)
+    {
+      if (bgp_dump_all.interval_str)
+	vty_out (vty, "dump bgp all %s %s%s", 
+		 bgp_dump_all.filename, bgp_dump_all.interval_str,
+		 VTY_NEWLINE);
+      else
+	vty_out (vty, "dump bgp all %s%s", 
+		 bgp_dump_all.filename, VTY_NEWLINE);
+    }
+  if (bgp_dump_updates.filename)
+    {
+      if (bgp_dump_updates.interval_str)
+	vty_out (vty, "dump bgp updates %s %s%s", 
+		 bgp_dump_updates.filename, bgp_dump_updates.interval_str,
+		 VTY_NEWLINE);
+      else
+	vty_out (vty, "dump bgp updates %s%s", 
+		 bgp_dump_updates.filename, VTY_NEWLINE);
+    }
+  if (bgp_dump_routes.filename)
+    {
+      if (bgp_dump_routes.interval_str)
+	vty_out (vty, "dump bgp routes-mrt %s %s%s", 
+		 bgp_dump_routes.filename, bgp_dump_routes.interval_str,
+		 VTY_NEWLINE);
+      else
+	vty_out (vty, "dump bgp routes-mrt %s%s", 
+		 bgp_dump_routes.filename, VTY_NEWLINE);
+    }
+  return 0;
+}
+
+/* Initialize BGP packet dump functionality. */
+void
+bgp_dump_init ()
+{
+  memset (&bgp_dump_all, 0, sizeof (struct bgp_dump));
+  memset (&bgp_dump_updates, 0, sizeof (struct bgp_dump));
+  memset (&bgp_dump_routes, 0, sizeof (struct bgp_dump));
+
+  bgp_dump_obuf = stream_new (BGP_MAX_PACKET_SIZE + BGP_DUMP_HEADER_SIZE);
+
+  install_node (&bgp_dump_node, config_write_bgp_dump);
+
+  install_element (CONFIG_NODE, &dump_bgp_all_cmd);
+  install_element (CONFIG_NODE, &dump_bgp_all_interval_cmd);
+  install_element (CONFIG_NODE, &no_dump_bgp_all_cmd);
+  install_element (CONFIG_NODE, &dump_bgp_updates_cmd);
+  install_element (CONFIG_NODE, &dump_bgp_updates_interval_cmd);
+  install_element (CONFIG_NODE, &no_dump_bgp_updates_cmd);
+  install_element (CONFIG_NODE, &dump_bgp_routes_cmd);
+  install_element (CONFIG_NODE, &dump_bgp_routes_interval_cmd);
+  install_element (CONFIG_NODE, &no_dump_bgp_routes_cmd);
+}
diff --git a/bgpd/bgp_dump.h b/bgpd/bgp_dump.h
new file mode 100644
index 0000000..d2f96a9
--- /dev/null
+++ b/bgpd/bgp_dump.h
@@ -0,0 +1,34 @@
+/* BGP dump routine.
+   Copyright (C) 1999 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+/* MRT compatible packet dump values.  */
+/* type value */
+#define MSG_PROTOCOL_BGP4MP  16
+/* subtype value */
+#define BGP4MP_STATE_CHANGE   0
+#define BGP4MP_MESSAGE        1
+#define BGP4MP_ENTRY          2
+#define BGP4MP_SNAPSHOT       3
+
+#define BGP_DUMP_HEADER_SIZE 12
+
+void bgp_dump_init ();
+void bgp_dump_state (struct peer *, int, int);
+void bgp_dump_packet (struct peer *, int, struct stream *);
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
new file mode 100644
index 0000000..2f9cc94
--- /dev/null
+++ b/bgpd/bgp_ecommunity.c
@@ -0,0 +1,641 @@
+/* BGP Extended Communities Attribute
+   Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "hash.h"
+#include "memory.h"
+#include "prefix.h"
+#include "command.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_ecommunity.h"
+
+/* Hash of community attribute. */
+struct hash *ecomhash;
+
+/* Allocate a new ecommunities.  */
+struct ecommunity *
+ecommunity_new ()
+{
+  return (struct ecommunity *) XCALLOC (MTYPE_ECOMMUNITY,
+					sizeof (struct ecommunity));
+}
+
+/* Allocate ecommunities.  */
+void
+ecommunity_free (struct ecommunity *ecom)
+{
+  if (ecom->val)
+    XFREE (MTYPE_ECOMMUNITY_VAL, ecom->val);
+  if (ecom->str)
+    XFREE (MTYPE_ECOMMUNITY_STR, ecom->str);
+  XFREE (MTYPE_ECOMMUNITY, ecom);
+}
+
+/* Add a new Extended Communities value to Extended Communities
+   Attribute structure.  When the value is already exists in the
+   structure, we don't add the value.  Newly added value is sorted by
+   numerical order.  When the value is added to the structure return 1
+   else return 0.  */
+static int
+ecommunity_add_val (struct ecommunity *ecom, struct ecommunity_val *eval)
+{
+  u_char *p;
+  int ret;
+  int c;
+
+  /* When this is fist value, just add it.  */
+  if (ecom->val == NULL)
+    {
+      ecom->size++;
+      ecom->val = XMALLOC (MTYPE_ECOMMUNITY_VAL, ecom_length (ecom));
+      memcpy (ecom->val, eval->val, ECOMMUNITY_SIZE);
+      return 1;
+    }
+
+  /* If the value already exists in the structure return 0.  */
+  c = 0;
+  for (p = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++)
+    {
+      ret = memcmp (p, eval->val, ECOMMUNITY_SIZE);
+      if (ret == 0)
+        return 0;
+      if (ret > 0)
+        break;
+    }
+
+  /* Add the value to the structure with numerical sorting.  */
+  ecom->size++;
+  ecom->val = XREALLOC (MTYPE_ECOMMUNITY_VAL, ecom->val, ecom_length (ecom));
+
+  memmove (ecom->val + (c + 1) * ECOMMUNITY_SIZE,
+	   ecom->val + c * ECOMMUNITY_SIZE,
+	   (ecom->size - 1 - c) * ECOMMUNITY_SIZE);
+  memcpy (ecom->val + c * ECOMMUNITY_SIZE, eval->val, ECOMMUNITY_SIZE);
+
+  return 1;
+}
+
+/* This function takes pointer to Extended Communites strucutre then
+   create a new Extended Communities structure by uniq and sort each
+   Exteneded Communities value.  */
+struct ecommunity *
+ecommunity_uniq_sort (struct ecommunity *ecom)
+{
+  int i;
+  struct ecommunity *new;
+  struct ecommunity_val *eval;
+  
+  if (! ecom)
+    return NULL;
+  
+  new = ecommunity_new ();;
+  
+  for (i = 0; i < ecom->size; i++)
+    {
+      eval = (struct ecommunity_val *) (ecom->val + (i * ECOMMUNITY_SIZE));
+      ecommunity_add_val (new, eval);
+    }
+  return new;
+}
+
+/* Parse Extended Communites Attribute in BGP packet.  */
+struct ecommunity *
+ecommunity_parse (char *pnt, u_short length)
+{
+  struct ecommunity tmp;
+  struct ecommunity *new;
+
+  /* Length check.  */
+  if (length % ECOMMUNITY_SIZE)
+    return NULL;
+
+  /* Prepare tmporary structure for making a new Extended Communities
+     Attribute.  */
+  tmp.size = length / ECOMMUNITY_SIZE;
+  tmp.val = pnt;
+
+  /* Create a new Extended Communities Attribute by uniq and sort each
+     Extended Communities value  */
+  new = ecommunity_uniq_sort (&tmp);
+
+  return ecommunity_intern (new);
+}
+
+/* Duplicate the Extended Communities Attribute structure.  */
+struct ecommunity *
+ecommunity_dup (struct ecommunity *ecom)
+{
+  struct ecommunity *new;
+
+  new = XCALLOC (MTYPE_ECOMMUNITY, sizeof (struct ecommunity));
+  new->size = ecom->size;
+  if (new->size)
+    {
+      new->val = XMALLOC (MTYPE_ECOMMUNITY_VAL, ecom->size * ECOMMUNITY_SIZE);
+      memcpy (new->val, ecom->val, ecom->size * ECOMMUNITY_SIZE);
+    }
+  else
+    new->val = NULL;
+  return new;
+}
+
+/* Merge two Extended Communities Attribute structure.  */
+struct ecommunity *
+ecommunity_merge (struct ecommunity *ecom1, struct ecommunity *ecom2)
+{
+  if (ecom1->val)
+    ecom1->val = XREALLOC (MTYPE_ECOMMUNITY_VAL, ecom1->val, 
+			   (ecom1->size + ecom2->size) * ECOMMUNITY_SIZE);
+  else
+    ecom1->val = XMALLOC (MTYPE_ECOMMUNITY_VAL,
+			  (ecom1->size + ecom2->size) * ECOMMUNITY_SIZE);
+
+  memcpy (ecom1->val + (ecom1->size * ECOMMUNITY_SIZE),
+	  ecom2->val, ecom2->size * ECOMMUNITY_SIZE);
+  ecom1->size += ecom2->size;
+
+  return ecom1;
+}
+
+/* Intern Extended Communities Attribute.  */
+struct ecommunity *
+ecommunity_intern (struct ecommunity *ecom)
+{
+  struct ecommunity *find;
+
+  assert (ecom->refcnt == 0);
+
+  find = (struct ecommunity *) hash_get (ecomhash, ecom, hash_alloc_intern);
+
+  if (find != ecom)
+    ecommunity_free (ecom);
+
+  find->refcnt++;
+
+  if (! find->str)
+    find->str = ecommunity_ecom2str (find, ECOMMUNITY_FORMAT_DISPLAY);
+
+  return find;
+}
+
+/* Unintern Extended Communities Attribute.  */
+void
+ecommunity_unintern (struct ecommunity *ecom)
+{
+  struct ecommunity *ret;
+
+  if (ecom->refcnt)
+    ecom->refcnt--;
+
+  /* Pull off from hash.  */
+  if (ecom->refcnt == 0)
+    {
+      /* Extended community must be in the hash.  */
+      ret = (struct ecommunity *) hash_release (ecomhash, ecom);
+      assert (ret != NULL);
+
+      ecommunity_free (ecom);
+    }
+}
+
+/* Utinity function to make hash key.  */
+unsigned int
+ecommunity_hash_make (struct ecommunity *ecom)
+{
+  int c;
+  unsigned int key;
+  unsigned char *pnt;
+
+  key = 0;
+  pnt = ecom->val;
+  
+  for (c = 0; c < ecom->size * ECOMMUNITY_SIZE; c++)
+    key += pnt[c];
+
+  return key;
+}
+
+/* Compare two Extended Communities Attribute structure.  */
+int
+ecommunity_cmp (struct ecommunity *ecom1, struct ecommunity *ecom2)
+{
+  if (ecom1->size == ecom2->size
+      && memcmp (ecom1->val, ecom2->val, ecom1->size * ECOMMUNITY_SIZE) == 0)
+    return 1;
+  return 0;
+}
+
+/* Initialize Extended Comminities related hash. */
+void
+ecommunity_init ()
+{
+  ecomhash = hash_create (ecommunity_hash_make, ecommunity_cmp);
+}
+
+/* Extended Communities token enum. */
+enum ecommunity_token
+{
+  ecommunity_token_rt,
+  ecommunity_token_soo,
+  ecommunity_token_val,
+  ecommunity_token_unknown
+};
+
+/* Get next Extended Communities token from the string. */
+char *
+ecommunity_gettoken (char *str, struct ecommunity_val *eval,
+		     enum ecommunity_token *token)
+{
+  int ret;
+  int dot = 0;
+  int digit = 0;
+  int separator = 0;
+  u_int32_t val_low = 0;
+  u_int32_t val_high = 0;
+  char *p = str;
+  struct in_addr ip;
+  char ipstr[INET_ADDRSTRLEN + 1];
+
+  /* Skip white space. */
+  while (isspace ((int) *p))
+    {
+      p++;
+      str++;
+    }
+
+  /* Check the end of the line. */
+  if (*p == '\0')
+    return NULL;
+
+  /* "rt" and "soo" keyword parse. */
+  if (! isdigit ((int) *p)) 
+    {
+      /* "rt" match check.  */
+      if (tolower ((int) *p) == 'r')
+	{
+	  p++;
+ 	  if (tolower ((int) *p) == 't')
+	    {
+	      p++;
+	      *token = ecommunity_token_rt;
+	      return p;
+	    }
+	  if (isspace ((int) *p) || *p == '\0')
+	    {
+	      *token = ecommunity_token_rt;
+	      return p;
+	    }
+	  goto error;
+	}
+      /* "soo" match check.  */
+      else if (tolower ((int) *p) == 's')
+	{
+	  p++;
+ 	  if (tolower ((int) *p) == 'o')
+	    {
+	      p++;
+	      if (tolower ((int) *p) == 'o')
+		{
+		  p++;
+		  *token = ecommunity_token_soo;
+		  return p;
+		}
+	      if (isspace ((int) *p) || *p == '\0')
+		{
+		  *token = ecommunity_token_soo;
+		  return p;
+		}
+	      goto error;
+	    }
+	  if (isspace ((int) *p) || *p == '\0')
+	    {
+	      *token = ecommunity_token_soo;
+	      return p;
+	    }
+	  goto error;
+	}
+      goto error;
+    }
+  
+  while (isdigit ((int) *p) || *p == ':' || *p == '.') 
+    {
+      if (*p == ':') 
+	{
+	  if (separator)
+	    goto error;
+
+	  separator = 1;
+	  digit = 0;
+
+	  if (dot)
+	    {
+	      if ((p - str) > INET_ADDRSTRLEN)
+		goto error;
+
+	      memset (ipstr, 0, INET_ADDRSTRLEN + 1);
+	      memcpy (ipstr, str, p - str);
+
+	      ret = inet_aton (ipstr, &ip);
+	      if (ret == 0)
+		goto error;
+	    }
+	  else
+	    val_high = val_low;
+
+	  val_low = 0;
+	}
+      else if (*p == '.')
+	{
+	  if (separator)
+	    goto error;
+	  dot++;
+	  if (dot > 4)
+	    goto error;
+	}
+      else
+	{
+	  digit = 1;
+	  val_low *= 10;
+	  val_low += (*p - '0');
+	}
+      p++;
+    }
+
+  /* Low digit part must be there. */
+  if (! digit || ! separator)
+    goto error;
+
+  /* Encode result into routing distinguisher.  */
+  if (dot)
+    {
+      eval->val[0] = ECOMMUNITY_ENCODE_IP;
+      eval->val[1] = 0;
+      memcpy (&eval->val[2], &ip, sizeof (struct in_addr));
+      eval->val[6] = (val_low >> 8) & 0xff;
+      eval->val[7] = val_low & 0xff;
+    }
+  else
+    {
+      eval->val[0] = ECOMMUNITY_ENCODE_AS;
+      eval->val[1] = 0;
+      eval->val[2] = (val_high >>8) & 0xff;
+      eval->val[3] = val_high & 0xff;
+      eval->val[4] = (val_low >>24) & 0xff;
+      eval->val[5] = (val_low >>16) & 0xff;
+      eval->val[6] = (val_low >>8) & 0xff;
+      eval->val[7] = val_low & 0xff;
+    }
+  *token = ecommunity_token_val;
+  return p;
+
+ error:
+  *token = ecommunity_token_unknown;
+  return p;
+}
+
+/* Convert string to extended community attribute. 
+
+   When type is already known, please specify both str and type.  str
+   should not include keyword such as "rt" and "soo".  Type is
+   ECOMMUNITY_ROUTE_TARGET or ECOMMUNITY_SITE_ORIGIN.
+   keyword_included should be zero.
+
+   For example route-map's "set extcommunity" command case:
+
+   "rt 100:1 100:2 100:3"        -> str = "100:1 100:2 100:3"
+                                    type = ECOMMUNITY_ROUTE_TARGET
+                                    keyword_included = 0
+
+   "soo 100:1"                   -> str = "100:1"
+                                    type = ECOMMUNITY_SITE_ORIGIN
+                                    keyword_included = 0
+
+   When string includes keyword for each extended community value.
+   Please specify keyword_included as non-zero value.
+
+   For example standard extcommunity-list case:
+
+   "rt 100:1 rt 100:2 soo 100:1" -> str = "rt 100:1 rt 100:2 soo 100:1"
+                                    type = 0
+                                    keyword_include = 1
+*/
+struct ecommunity *
+ecommunity_str2com (char *str, int type, int keyword_included)
+{
+  struct ecommunity *ecom = NULL;
+  enum ecommunity_token token;
+  struct ecommunity_val eval;
+  int keyword = 0;
+
+  while ((str = ecommunity_gettoken (str, &eval, &token)))
+    {
+      switch (token)
+	{
+	case ecommunity_token_rt:
+	case ecommunity_token_soo:
+	  if (! keyword_included || keyword)
+	    {
+	      if (ecom)
+		ecommunity_free (ecom);
+	      return NULL;
+	    }
+	  keyword = 1;
+
+	  if (token == ecommunity_token_rt)
+	    {
+	      type = ECOMMUNITY_ROUTE_TARGET;
+	    }
+	  if (token == ecommunity_token_soo)
+	    {
+	      type = ECOMMUNITY_SITE_ORIGIN;
+	    }
+	  break;
+	case ecommunity_token_val:
+	  if (keyword_included)
+	    {
+	      if (! keyword)
+		{
+		  if (ecom)
+		    ecommunity_free (ecom);
+		  return NULL;
+		}
+	      keyword = 0;
+	    }
+	  if (ecom == NULL)
+	    ecom = ecommunity_new ();
+	  eval.val[1] = type;
+	  ecommunity_add_val (ecom, &eval);
+	  break;
+	case ecommunity_token_unknown:
+	default:
+	  if (ecom)
+	    ecommunity_free (ecom);
+	  return NULL;
+	  break;
+	}
+    }
+  return ecom;
+}
+
+/* Convert extended community attribute to string.  
+
+   Due to historical reason of industry standard implementation, there
+   are three types of format.
+
+   route-map set extcommunity format
+        "rt 100:1 100:2"
+        "soo 100:3"
+
+   extcommunity-list
+        "rt 100:1 rt 100:2 soo 100:3"
+
+   "show ip bgp" and extcommunity-list regular expression matching
+        "RT:100:1 RT:100:2 SoO:100:3"
+
+   For each formath please use below definition for format:
+
+   ECOMMUNITY_FORMAT_ROUTE_MAP
+   ECOMMUNITY_FORMAT_COMMUNITY_LIST
+   ECOMMUNITY_FORMAT_DISPLAY
+*/
+char *
+ecommunity_ecom2str (struct ecommunity *ecom, int format)
+{
+  int i;
+  u_char *pnt;
+  int encode = 0;
+  int type = 0;
+#define ECOMMUNITY_STR_DEFAULT_LEN  26
+  int str_size;
+  int str_pnt;
+  u_char *str_buf;
+  char *prefix;
+  int len = 0;
+  int first = 1;
+
+  /* For parse Extended Community attribute tupple. */
+  struct ecommunity_as
+  {
+    as_t as;
+    u_int32_t val;
+  } eas;
+
+  struct ecommunity_ip
+  {
+    struct in_addr ip;
+    u_int16_t val;
+  } eip;
+
+  if (ecom->size == 0)
+    {
+      str_buf = XMALLOC (MTYPE_ECOMMUNITY_STR, 1);
+      str_buf[0] = '\0';
+      return str_buf;
+    }
+
+  /* Prepare buffer.  */
+  str_buf = XMALLOC (MTYPE_ECOMMUNITY_STR, ECOMMUNITY_STR_DEFAULT_LEN + 1);
+  str_size = ECOMMUNITY_STR_DEFAULT_LEN + 1;
+  str_pnt = 0;
+
+  for (i = 0; i < ecom->size; i++)
+    {
+      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";
+	}
+      
+      /* 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";
+	}
+
+      switch (format)
+	{
+	case ECOMMUNITY_FORMAT_COMMUNITY_LIST:
+	  prefix = (type == ECOMMUNITY_ROUTE_TARGET ? "rt " : "soo ");
+	  break;
+	case ECOMMUNITY_FORMAT_DISPLAY:
+	  prefix = (type == ECOMMUNITY_ROUTE_TARGET ? "RT:" : "SoO:");
+	  break;
+	case ECOMMUNITY_FORMAT_ROUTE_MAP:
+	  prefix = "";
+	  break;
+	default:
+	  if (str_buf)
+	    XFREE (MTYPE_ECOMMUNITY_STR, str_buf);
+	  return "Unknown";
+	  break;
+	}
+
+      /* Make it sure size is enough.  */
+      while (str_pnt + ECOMMUNITY_STR_DEFAULT_LEN >= str_size)
+	{
+	  str_size *= 2;
+	  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)
+	{
+	  eas.as = (*pnt++ << 8);
+	  eas.as |= (*pnt++);
+
+	  eas.val = (*pnt++ << 24);
+	  eas.val |= (*pnt++ << 16);
+	  eas.val |= (*pnt++ << 8);
+	  eas.val |= (*pnt++);
+
+	  len = sprintf (str_buf + str_pnt, "%s%d:%d", prefix,
+			 eas.as, eas.val);
+	  str_pnt += len;
+	  first = 0;
+	}
+      else if (encode == ECOMMUNITY_ENCODE_IP)
+	{
+	  memcpy (&eip.ip, pnt, 4);
+	  pnt += 4;
+	  eip.val = (*pnt++ << 8);
+	  eip.val |= (*pnt++);
+
+	  len = sprintf (str_buf + str_pnt, "%s%s:%d", prefix,
+			 inet_ntoa (eip.ip), eip.val);
+	  str_pnt += len;
+	  first = 0;
+	}
+    }
+  return str_buf;
+}
diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h
new file mode 100644
index 0000000..678d130
--- /dev/null
+++ b/bgpd/bgp_ecommunity.h
@@ -0,0 +1,72 @@
+/* BGP Extended Communities Attribute.
+   Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+/* High-order octet of the Extended Communities type field.  */
+#define ECOMMUNITY_ENCODE_AS                0x00
+#define ECOMMUNITY_ENCODE_IP                0x01
+
+/* Low-order octet of the Extended Communityes type field.  */
+#define ECOMMUNITY_ROUTE_TARGET             0x02
+#define ECOMMUNITY_SITE_ORIGIN              0x03
+
+/* Extended communities attribute string format.  */
+#define ECOMMUNITY_FORMAT_ROUTE_MAP            0
+#define ECOMMUNITY_FORMAT_COMMUNITY_LIST       1
+#define ECOMMUNITY_FORMAT_DISPLAY              2
+
+/* Extended Communities value is eight octet long.  */
+#define ECOMMUNITY_SIZE                        8
+
+/* Extended Communities attribute.  */
+struct ecommunity
+{
+  /* Reference counter.  */
+  unsigned long refcnt;
+
+  /* Size of Extended Communities attribute.  */
+  int size;
+
+  /* Extended Communities value.  */
+  u_char *val;
+
+  /* Human readable format string.  */
+  char *str;
+};
+
+/* Extended community value is eight octet.  */
+struct ecommunity_val
+{
+  char val[ECOMMUNITY_SIZE];
+};
+
+#define ecom_length(X)    ((X)->size * ECOMMUNITY_SIZE)
+
+void ecommunity_init (void);
+void ecommunity_free (struct ecommunity *);
+struct ecommunity *ecommunity_new (void);
+struct ecommunity *ecommunity_parse (char *, u_short);
+struct ecommunity *ecommunity_dup (struct ecommunity *);
+struct ecommunity *ecommunity_merge (struct ecommunity *, struct ecommunity *);
+struct ecommunity *ecommunity_intern (struct ecommunity *);
+int ecommunity_cmp (struct ecommunity *, struct ecommunity *);
+void ecommunity_unintern (struct ecommunity *);
+unsigned int ecommunity_hash_make (struct ecommunity *);
+struct ecommunity *ecommunity_str2com (char *, int, int);
+char *ecommunity_ecom2str (struct ecommunity *, int);
diff --git a/bgpd/bgp_filter.c b/bgpd/bgp_filter.c
new file mode 100644
index 0000000..b544c71
--- /dev/null
+++ b/bgpd/bgp_filter.c
@@ -0,0 +1,658 @@
+/* AS path filter list.
+   Copyright (C) 1999 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "command.h"
+#include "log.h"
+#include "memory.h"
+#include "buffer.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_aspath.h"
+#include "bgpd/bgp_regex.h"
+#include "bgpd/bgp_filter.h"
+
+/* List of AS filter list. */
+struct as_list_list
+{
+  struct as_list *head;
+  struct as_list *tail;
+};
+
+/* AS path filter master. */
+struct as_list_master
+{
+  /* List of access_list which name is number. */
+  struct as_list_list num;
+
+  /* List of access_list which name is string. */
+  struct as_list_list str;
+
+  /* Hook function which is executed when new access_list is added. */
+  void (*add_hook) ();
+
+  /* Hook function which is executed when access_list is deleted. */
+  void (*delete_hook) ();
+};
+
+/* Element of AS path filter. */
+struct as_filter
+{
+  struct as_filter *next;
+  struct as_filter *prev;
+
+  enum as_filter_type type;
+
+  regex_t *reg;
+  char *reg_str;
+};
+
+enum as_list_type
+{
+  ACCESS_TYPE_STRING,
+  ACCESS_TYPE_NUMBER
+};
+
+/* AS path filter list. */
+struct as_list
+{
+  char *name;
+
+  enum as_list_type type;
+
+  struct as_list *next;
+  struct as_list *prev;
+
+  struct as_filter *head;
+  struct as_filter *tail;
+};
+
+/* ip as-path access-list 10 permit AS1. */
+
+static struct as_list_master as_list_master =
+{
+  {NULL, NULL},
+  {NULL, NULL},
+  NULL,
+  NULL
+};
+
+/* Allocate new AS filter. */
+struct as_filter *
+as_filter_new ()
+{
+  struct as_filter *new;
+
+  new = XMALLOC (MTYPE_AS_FILTER, sizeof (struct as_filter));
+  memset (new, 0, sizeof (struct as_filter));
+  return new;
+}
+
+/* Free allocated AS filter. */
+void
+as_filter_free (struct as_filter *asfilter)
+{
+  if (asfilter->reg)
+    bgp_regex_free (asfilter->reg);
+  if (asfilter->reg_str)
+    XFREE (MTYPE_AS_FILTER_STR, asfilter->reg_str);
+  XFREE (MTYPE_AS_FILTER, asfilter);
+}
+
+/* Make new AS filter. */
+struct as_filter *
+as_filter_make (regex_t *reg, char *reg_str, enum as_filter_type type)
+{
+  struct as_filter *asfilter;
+
+  asfilter = as_filter_new ();
+  asfilter->reg = reg;
+  asfilter->type = type;
+  asfilter->reg_str = XSTRDUP (MTYPE_AS_FILTER_STR, reg_str);
+
+  return asfilter;
+}
+
+struct as_filter *
+as_filter_lookup (struct as_list *aslist, char *reg_str,
+		  enum as_filter_type type)
+{
+  struct as_filter *asfilter;
+
+  for (asfilter = aslist->head; asfilter; asfilter = asfilter->next)
+    if (strcmp (reg_str, asfilter->reg_str) == 0)
+      return asfilter;
+  return NULL;
+}
+
+void
+as_list_filter_add (struct as_list *aslist, struct as_filter *asfilter)
+{
+  asfilter->next = NULL;
+  asfilter->prev = aslist->tail;
+
+  if (aslist->tail)
+    aslist->tail->next = asfilter;
+  else
+    aslist->head = asfilter;
+  aslist->tail = asfilter;
+}
+
+/* Lookup as_list from list of as_list by name. */
+struct as_list *
+as_list_lookup (char *name)
+{
+  struct as_list *aslist;
+
+  if (name == NULL)
+    return NULL;
+
+  for (aslist = as_list_master.num.head; aslist; aslist = aslist->next)
+    if (strcmp (aslist->name, name) == 0)
+      return aslist;
+
+  for (aslist = as_list_master.str.head; aslist; aslist = aslist->next)
+    if (strcmp (aslist->name, name) == 0)
+      return aslist;
+
+  return NULL;
+}
+
+struct as_list *
+as_list_new ()
+{
+  struct as_list *new;
+
+  new = XMALLOC (MTYPE_AS_LIST, sizeof (struct as_list));
+  memset (new, 0, sizeof (struct as_list));
+  return new;
+}
+
+void
+as_list_free (struct as_list *aslist)
+{
+  XFREE (MTYPE_AS_LIST, aslist);
+}
+
+/* Insert new AS list to list of as_list.  Each as_list is sorted by
+   the name. */
+struct as_list *
+as_list_insert (char *name)
+{
+  int i;
+  long number;
+  struct as_list *aslist;
+  struct as_list *point;
+  struct as_list_list *list;
+
+  /* Allocate new access_list and copy given name. */
+  aslist = as_list_new ();
+  aslist->name = strdup (name);
+
+  /* If name is made by all digit character.  We treat it as
+     number. */
+  for (number = 0, i = 0; i < strlen (name); i++)
+    {
+      if (isdigit ((int) name[i]))
+	number = (number * 10) + (name[i] - '0');
+      else
+	break;
+    }
+
+  /* In case of name is all digit character */
+  if (i == strlen (name))
+    {
+      aslist->type = ACCESS_TYPE_NUMBER;
+
+      /* Set access_list to number list. */
+      list = &as_list_master.num;
+
+      for (point = list->head; point; point = point->next)
+	if (atol (point->name) >= number)
+	  break;
+    }
+  else
+    {
+      aslist->type = ACCESS_TYPE_STRING;
+
+      /* Set access_list to string list. */
+      list = &as_list_master.str;
+  
+      /* Set point to insertion point. */
+      for (point = list->head; point; point = point->next)
+	if (strcmp (point->name, name) >= 0)
+	  break;
+    }
+
+  /* In case of this is the first element of master. */
+  if (list->head == NULL)
+    {
+      list->head = list->tail = aslist;
+      return aslist;
+    }
+
+  /* In case of insertion is made at the tail of access_list. */
+  if (point == NULL)
+    {
+      aslist->prev = list->tail;
+      list->tail->next = aslist;
+      list->tail = aslist;
+      return aslist;
+    }
+
+  /* In case of insertion is made at the head of access_list. */
+  if (point == list->head)
+    {
+      aslist->next = list->head;
+      list->head->prev = aslist;
+      list->head = aslist;
+      return aslist;
+    }
+
+  /* Insertion is made at middle of the access_list. */
+  aslist->next = point;
+  aslist->prev = point->prev;
+
+  if (point->prev)
+    point->prev->next = aslist;
+  point->prev = aslist;
+
+  return aslist;
+}
+
+struct as_list *
+as_list_get (char *name)
+{
+  struct as_list *aslist;
+
+  aslist = as_list_lookup (name);
+  if (aslist == NULL)
+    {
+      aslist = as_list_insert (name);
+
+      /* Run hook function. */
+      if (as_list_master.add_hook)
+	(*as_list_master.add_hook) ();
+    }
+
+  return aslist;
+}
+
+static char *
+filter_type_str (enum as_filter_type type)
+{
+  switch (type)
+    {
+    case AS_FILTER_PERMIT:
+      return "permit";
+      break;
+    case AS_FILTER_DENY:
+      return "deny";
+      break;
+    default:
+      return "";
+      break;
+    }
+}
+
+void
+as_list_delete (struct as_list *aslist)
+{
+  struct as_list_list *list;
+  struct as_filter *filter, *next;
+
+  for (filter = aslist->head; filter; filter = next)
+    {
+      next = filter->next;
+      as_filter_free (filter);
+    }
+
+  if (aslist->type == ACCESS_TYPE_NUMBER)
+    list = &as_list_master.num;
+  else
+    list = &as_list_master.str;
+
+  if (aslist->next)
+    aslist->next->prev = aslist->prev;
+  else
+    list->tail = aslist->prev;
+
+  if (aslist->prev)
+    aslist->prev->next = aslist->next;
+  else
+    list->head = aslist->next;
+
+  as_list_free (aslist);
+}
+
+static int
+as_list_empty (struct as_list *aslist)
+{
+  if (aslist->head == NULL && aslist->tail == NULL)
+    return 1;
+  else
+    return 0;
+}
+
+void
+as_list_filter_delete (struct as_list *aslist, struct as_filter *asfilter)
+{
+  if (asfilter->next)
+    asfilter->next->prev = asfilter->prev;
+  else
+    aslist->tail = asfilter->prev;
+
+  if (asfilter->prev)
+    asfilter->prev->next = asfilter->next;
+  else
+    aslist->head = asfilter->next;
+
+  as_filter_free (asfilter);
+
+  /* If access_list becomes empty delete it from access_master. */
+  if (as_list_empty (aslist))
+    as_list_delete (aslist);
+
+  /* Run hook function. */
+  if (as_list_master.delete_hook)
+    (*as_list_master.delete_hook) ();
+}
+
+static int
+as_filter_match (struct as_filter *asfilter, struct aspath *aspath)
+{
+  if (bgp_regexec (asfilter->reg, aspath) != REG_NOMATCH)
+    return 1;
+  return 0;
+}
+
+/* Apply AS path filter to AS. */
+enum as_filter_type
+as_list_apply (struct as_list *aslist, void *object)
+{
+  struct as_filter *asfilter;
+  struct aspath *aspath;
+
+  aspath = (struct aspath *) object;
+
+  if (aslist == NULL)
+    return AS_FILTER_DENY;
+
+  for (asfilter = aslist->head; asfilter; asfilter = asfilter->next)
+    {
+      if (as_filter_match (asfilter, aspath))
+	return asfilter->type;
+    }
+  return AS_FILTER_DENY;
+}
+
+/* Add hook function. */
+void
+as_list_add_hook (void (*func) ())
+{
+  as_list_master.add_hook = func;
+}
+
+/* Delete hook function. */
+void
+as_list_delete_hook (void (*func) ())
+{
+  as_list_master.delete_hook = func;
+}
+
+int
+as_list_dup_check (struct as_list *aslist, struct as_filter *new)
+{
+  struct as_filter *asfilter;
+
+  for (asfilter = aslist->head; asfilter; asfilter = asfilter->next)
+    {
+      if (asfilter->type == new->type
+	  && strcmp (asfilter->reg_str, new->reg_str) == 0)
+	return 1;
+    }
+  return 0;
+}
+
+DEFUN (ip_as_path, ip_as_path_cmd,
+       "ip as-path access-list WORD (deny|permit) .LINE",
+       IP_STR
+       "BGP autonomous system path filter\n"
+       "Specify an access list name\n"
+       "Regular expression access list name\n"
+       "Specify packets to reject\n"
+       "Specify packets to forward\n"
+       "A regular-expression to match the BGP AS paths\n")
+{
+  enum as_filter_type type;
+  struct as_filter *asfilter;
+  struct as_list *aslist;
+  regex_t *regex;
+  struct buffer *b;
+  int i;
+  char *regstr;
+  int first = 0;
+
+  /* Check the filter type. */
+  if (strncmp (argv[1], "p", 1) == 0)
+    type = AS_FILTER_PERMIT;
+  else if (strncmp (argv[1], "d", 1) == 0)
+    type = AS_FILTER_DENY;
+  else
+    {
+      vty_out (vty, "filter type must be [permit|deny]%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Check AS path regex. */
+  b = buffer_new (1024);
+  for (i = 2; i < argc; i++)
+    {
+      if (first)
+	buffer_putc (b, ' ');
+      else
+	first = 1;
+
+      buffer_putstr (b, argv[i]);
+    }
+  buffer_putc (b, '\0');
+
+  regstr = buffer_getstr (b);
+  buffer_free (b);
+
+  regex = bgp_regcomp (regstr);
+  if (!regex)
+    {
+      free (regstr);
+      vty_out (vty, "can't compile regexp %s%s", argv[0],
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  asfilter = as_filter_make (regex, regstr, type);
+  
+  free (regstr);
+
+  /* Install new filter to the access_list. */
+  aslist = as_list_get (argv[0]);
+
+  /* Duplicate insertion check. */;
+  if (as_list_dup_check (aslist, asfilter))
+    as_filter_free (asfilter);
+  else
+    as_list_filter_add (aslist, asfilter);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ip_as_path,
+       no_ip_as_path_cmd,
+       "no ip as-path access-list WORD (deny|permit) .LINE",
+       NO_STR
+       IP_STR
+       "BGP autonomous system path filter\n"
+       "Specify an access list name\n"
+       "Regular expression access list name\n"
+       "Specify packets to reject\n"
+       "Specify packets to forward\n"
+       "A regular-expression to match the BGP AS paths\n")
+{
+  enum as_filter_type type;
+  struct as_filter *asfilter;
+  struct as_list *aslist;
+  struct buffer *b;
+  int i;
+  int first = 0;
+  char *regstr;
+  regex_t *regex;
+
+  /* Lookup AS list from AS path list. */
+  aslist = as_list_lookup (argv[0]);
+  if (aslist == NULL)
+    {
+      vty_out (vty, "ip as-path access-list %s doesn't exist%s", argv[0],
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Check the filter type. */
+  if (strncmp (argv[1], "p", 1) == 0)
+    type = AS_FILTER_PERMIT;
+  else if (strncmp (argv[1], "d", 1) == 0)
+    type = AS_FILTER_DENY;
+  else
+    {
+      vty_out (vty, "filter type must be [permit|deny]%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  
+  /* Compile AS path. */
+  b = buffer_new (1024);
+  for (i = 2; i < argc; i++)
+    {
+      if (first)
+	buffer_putc (b, ' ');
+      else
+	first = 1;
+
+      buffer_putstr (b, argv[i]);
+    }
+  buffer_putc (b, '\0');
+
+  regstr = buffer_getstr (b);
+  buffer_free (b);
+
+  regex = bgp_regcomp (regstr);
+  if (!regex)
+    {
+      free (regstr);
+      vty_out (vty, "can't compile regexp %s%s", argv[0],
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Lookup asfilter. */
+  asfilter = as_filter_lookup (aslist, regstr, type);
+
+  free (regstr);
+  bgp_regex_free (regex);
+
+  if (asfilter == NULL)
+    {
+      vty_out (vty, "%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  as_list_filter_delete (aslist, asfilter);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ip_as_path_all,
+       no_ip_as_path_all_cmd,
+       "no ip as-path access-list WORD",
+       NO_STR
+       IP_STR
+       "BGP autonomous system path filter\n"
+       "Specify an access list name\n"
+       "Regular expression access list name\n")
+{
+  struct as_list *aslist;
+
+  aslist = as_list_lookup (argv[0]);
+  if (aslist == NULL)
+    {
+      vty_out (vty, "ip as-path access-list %s doesn't exist%s", argv[0],
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  as_list_delete (aslist);
+
+  return CMD_SUCCESS;
+}
+
+int
+config_write_as_list (struct vty *vty)
+{
+  struct as_list *aslist;
+  struct as_filter *asfilter;
+  int write = 0;
+
+  for (aslist = as_list_master.num.head; aslist; aslist = aslist->next)
+    for (asfilter = aslist->head; asfilter; asfilter = asfilter->next)
+      {
+	vty_out (vty, "ip as-path access-list %s %s %s%s",
+		 aslist->name, filter_type_str (asfilter->type), 
+		 asfilter->reg_str,
+		 VTY_NEWLINE);
+	write++;
+      }
+
+  for (aslist = as_list_master.str.head; aslist; aslist = aslist->next)
+    for (asfilter = aslist->head; asfilter; asfilter = asfilter->next)
+      {
+	vty_out (vty, "ip as-path access-list %s %s %s%s",
+		 aslist->name, filter_type_str (asfilter->type), 
+		 asfilter->reg_str,
+		 VTY_NEWLINE);
+	write++;
+      }
+  return write;
+}
+
+struct cmd_node as_list_node =
+{
+  AS_LIST_NODE,
+  "",
+  1
+};
+
+/* Register functions. */
+void
+bgp_filter_init ()
+{
+  install_node (&as_list_node, config_write_as_list);
+
+  install_element (CONFIG_NODE, &ip_as_path_cmd);
+  install_element (CONFIG_NODE, &no_ip_as_path_cmd);
+  install_element (CONFIG_NODE, &no_ip_as_path_all_cmd);
+}
diff --git a/bgpd/bgp_filter.h b/bgpd/bgp_filter.h
new file mode 100644
index 0000000..8d55a22
--- /dev/null
+++ b/bgpd/bgp_filter.h
@@ -0,0 +1,31 @@
+/* AS path filter list.
+   Copyright (C) 1999 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+enum as_filter_type
+{
+  AS_FILTER_DENY,
+  AS_FILTER_PERMIT
+};
+
+enum as_filter_type as_list_apply (struct as_list *, void *);
+
+struct as_list *as_list_lookup (char *);
+void as_list_add_hook (void (*func) ());
+void as_list_delete_hook (void (*func) ());
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
new file mode 100644
index 0000000..64a4c1b
--- /dev/null
+++ b/bgpd/bgp_fsm.c
@@ -0,0 +1,864 @@
+/* BGP-4 Finite State Machine   
+   From RFC1771 [A Border Gateway Protocol 4 (BGP-4)]
+   Copyright (C) 1996, 97, 98 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "linklist.h"
+#include "prefix.h"
+#include "vty.h"
+#include "sockunion.h"
+#include "thread.h"
+#include "log.h"
+#include "stream.h"
+#include "memory.h"
+#include "plist.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_fsm.h"
+#include "bgpd/bgp_packet.h"
+#include "bgpd/bgp_network.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_dump.h"
+#include "bgpd/bgp_open.h"
+#ifdef HAVE_SNMP
+#include "bgpd/bgp_snmp.h"
+#endif /* HAVE_SNMP */
+
+/* BGP FSM (finite state machine) has three types of functions.  Type
+   one is thread functions.  Type two is event functions.  Type three
+   is FSM functions.  Timer functions are set by bgp_timer_set
+   function. */
+
+/* BGP event function. */
+int bgp_event (struct thread *);
+
+/* BGP thread functions. */
+static int bgp_start_timer (struct thread *);
+static int bgp_connect_timer (struct thread *);
+static int bgp_holdtime_timer (struct thread *);
+static int bgp_keepalive_timer (struct thread *);
+
+/* BGP FSM functions. */
+static int bgp_start (struct peer *);
+
+/* BGP start timer jitter. */
+int
+bgp_start_jitter (int time)
+{
+  return ((rand () % (time + 1)) - (time / 2));
+}
+
+/* Hook function called after bgp event is occered.  And vty's
+   neighbor command invoke this function after making neighbor
+   structure. */
+void
+bgp_timer_set (struct peer *peer)
+{
+  int jitter = 0;
+
+  switch (peer->status)
+    {
+    case Idle:
+      /* First entry point of peer's finite state machine.  In Idle
+	 status start timer is on unless peer is shutdown or peer is
+	 inactive.  All other timer must be turned off */
+      if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN)
+	  || CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW)
+	  || ! peer_active (peer))
+	{
+	  BGP_TIMER_OFF (peer->t_start);
+	}
+      else
+	{
+	  jitter = bgp_start_jitter (peer->v_start);
+	  BGP_TIMER_ON (peer->t_start, bgp_start_timer,
+			peer->v_start + jitter);
+	}
+      BGP_TIMER_OFF (peer->t_connect);
+      BGP_TIMER_OFF (peer->t_holdtime);
+      BGP_TIMER_OFF (peer->t_keepalive);
+      BGP_TIMER_OFF (peer->t_asorig);
+      BGP_TIMER_OFF (peer->t_routeadv);
+      break;
+
+    case Connect:
+      /* After start timer is expired, the peer moves to Connnect
+         status.  Make sure start timer is off and connect timer is
+         on. */
+      BGP_TIMER_OFF (peer->t_start);
+      BGP_TIMER_ON (peer->t_connect, bgp_connect_timer, peer->v_connect);
+      BGP_TIMER_OFF (peer->t_holdtime);
+      BGP_TIMER_OFF (peer->t_keepalive);
+      BGP_TIMER_OFF (peer->t_asorig);
+      BGP_TIMER_OFF (peer->t_routeadv);
+      break;
+
+    case Active:
+      /* Active is waiting connection from remote peer.  And if
+         connect timer is expired, change status to Connect. */
+      BGP_TIMER_OFF (peer->t_start);
+      /* If peer is passive mode, do not set connect timer. */
+      if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
+	{
+	  BGP_TIMER_OFF (peer->t_connect);
+	}
+      else
+	{
+	  BGP_TIMER_ON (peer->t_connect, bgp_connect_timer, peer->v_connect);
+	}
+      BGP_TIMER_OFF (peer->t_holdtime);
+      BGP_TIMER_OFF (peer->t_keepalive);
+      BGP_TIMER_OFF (peer->t_asorig);
+      BGP_TIMER_OFF (peer->t_routeadv);
+      break;
+
+    case OpenSent:
+      /* OpenSent status. */
+      BGP_TIMER_OFF (peer->t_start);
+      BGP_TIMER_OFF (peer->t_connect);
+      if (peer->v_holdtime != 0)
+	{
+	  BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer, 
+			peer->v_holdtime);
+	}
+      else
+	{
+	  BGP_TIMER_OFF (peer->t_holdtime);
+	}
+      BGP_TIMER_OFF (peer->t_keepalive);
+      BGP_TIMER_OFF (peer->t_asorig);
+      BGP_TIMER_OFF (peer->t_routeadv);
+      break;
+
+    case OpenConfirm:
+      /* OpenConfirm status. */
+      BGP_TIMER_OFF (peer->t_start);
+      BGP_TIMER_OFF (peer->t_connect);
+
+      /* If the negotiated Hold Time value is zero, then the Hold Time
+         timer and KeepAlive timers are not started. */
+      if (peer->v_holdtime == 0)
+	{
+	  BGP_TIMER_OFF (peer->t_holdtime);
+	  BGP_TIMER_OFF (peer->t_keepalive);
+	}
+      else
+	{
+	  BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer,
+			peer->v_holdtime);
+	  BGP_TIMER_ON (peer->t_keepalive, bgp_keepalive_timer, 
+			peer->v_keepalive);
+	}
+      BGP_TIMER_OFF (peer->t_asorig);
+      BGP_TIMER_OFF (peer->t_routeadv);
+      break;
+
+    case Established:
+      /* In Established status start and connect timer is turned
+         off. */
+      BGP_TIMER_OFF (peer->t_start);
+      BGP_TIMER_OFF (peer->t_connect);
+
+      /* Same as OpenConfirm, if holdtime is zero then both holdtime
+         and keepalive must be turned off. */
+      if (peer->v_holdtime == 0)
+	{
+	  BGP_TIMER_OFF (peer->t_holdtime);
+	  BGP_TIMER_OFF (peer->t_keepalive);
+	}
+      else
+	{
+	  BGP_TIMER_ON (peer->t_holdtime, bgp_holdtime_timer,
+			peer->v_holdtime);
+	  BGP_TIMER_ON (peer->t_keepalive, bgp_keepalive_timer,
+			peer->v_keepalive);
+	}
+      BGP_TIMER_OFF (peer->t_asorig);
+      break;
+    }
+}
+
+/* BGP start timer.  This function set BGP_Start event to thread value
+   and process event. */
+static int
+bgp_start_timer (struct thread *thread)
+{
+  struct peer *peer;
+
+  peer = THREAD_ARG (thread);
+  peer->t_start = NULL;
+
+  if (BGP_DEBUG (fsm, FSM))
+    zlog (peer->log, LOG_DEBUG,
+	  "%s [FSM] Timer (start timer expire).", peer->host);
+
+  THREAD_VAL (thread) = BGP_Start;
+  bgp_event (thread);
+
+  return 0;
+}
+
+/* BGP connect retry timer. */
+static int
+bgp_connect_timer (struct thread *thread)
+{
+  struct peer *peer;
+
+  peer = THREAD_ARG (thread);
+  peer->t_connect = NULL;
+
+  if (BGP_DEBUG (fsm, FSM))
+    zlog (peer->log, LOG_DEBUG, "%s [FSM] Timer (connect timer expire)",
+	  peer->host);
+
+  THREAD_VAL (thread) = ConnectRetry_timer_expired;
+  bgp_event (thread);
+
+  return 0;
+}
+
+/* BGP holdtime timer. */
+static int
+bgp_holdtime_timer (struct thread *thread)
+{
+  struct peer *peer;
+
+  peer = THREAD_ARG (thread);
+  peer->t_holdtime = NULL;
+
+  if (BGP_DEBUG (fsm, FSM))
+    zlog (peer->log, LOG_DEBUG,
+	  "%s [FSM] Timer (holdtime timer expire)",
+	  peer->host);
+
+  THREAD_VAL (thread) = Hold_Timer_expired;
+  bgp_event (thread);
+
+  return 0;
+}
+
+/* BGP keepalive fire ! */
+static int
+bgp_keepalive_timer (struct thread *thread)
+{
+  struct peer *peer;
+
+  peer = THREAD_ARG (thread);
+  peer->t_keepalive = NULL;
+
+  if (BGP_DEBUG (fsm, FSM))
+    zlog (peer->log, LOG_DEBUG,
+	  "%s [FSM] Timer (keepalive timer expire)",
+	  peer->host);
+
+  THREAD_VAL (thread) = KeepAlive_timer_expired;
+  bgp_event (thread);
+
+  return 0;
+}
+
+int
+bgp_routeadv_timer (struct thread *thread)
+{
+  struct peer *peer;
+
+  peer = THREAD_ARG (thread);
+  peer->t_routeadv = NULL;
+
+  if (BGP_DEBUG (fsm, FSM))
+    zlog (peer->log, LOG_DEBUG,
+	  "%s [FSM] Timer (routeadv timer expire)",
+	  peer->host);
+
+  peer->synctime = time (NULL);
+
+  BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+
+  BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer,
+		peer->v_routeadv);
+
+  return 0;
+}
+
+/* Reset bgp update timer */
+static void
+bgp_uptime_reset (struct peer *peer)
+{
+  peer->uptime = time (NULL);
+}
+
+/* Administrative BGP peer stop event. */
+int
+bgp_stop (struct peer *peer)
+{
+  int established = 0;
+  afi_t afi;
+  safi_t safi;
+  char orf_name[BUFSIZ];
+
+  /* Increment Dropped count. */
+  if (peer->status == Established)
+    {
+      established = 1;
+      peer->dropped++;
+      bgp_fsm_change_status (peer, Idle);
+#ifdef HAVE_SNMP
+      bgpTrapBackwardTransition (peer);
+#endif /* HAVE_SNMP */
+    }
+
+  /* Reset uptime. */
+  bgp_uptime_reset (peer);
+
+  /* Need of clear of peer. */
+  if (established)
+    bgp_clear_route_all (peer);
+
+  /* Stop read and write threads when exists. */
+  BGP_READ_OFF (peer->t_read);
+  BGP_WRITE_OFF (peer->t_write);
+
+  /* Stop all timers. */
+  BGP_TIMER_OFF (peer->t_start);
+  BGP_TIMER_OFF (peer->t_connect);
+  BGP_TIMER_OFF (peer->t_holdtime);
+  BGP_TIMER_OFF (peer->t_keepalive);
+  BGP_TIMER_OFF (peer->t_asorig);
+  BGP_TIMER_OFF (peer->t_routeadv);
+
+  /* Delete all existing events of the peer. */
+  BGP_EVENT_DELETE (peer);
+
+  /* Stream reset. */
+  peer->packet_size = 0;
+
+  /* Clear input and output buffer.  */
+  if (peer->ibuf)
+    stream_reset (peer->ibuf);
+  if (peer->work)
+    stream_reset (peer->work);
+  stream_fifo_clean (peer->obuf);
+
+  /* Close of file descriptor. */
+  if (peer->fd >= 0)
+    {
+      close (peer->fd);
+      peer->fd = -1;
+    }
+
+  /* Connection information. */
+  if (peer->su_local)
+    {
+      XFREE (MTYPE_SOCKUNION, peer->su_local);
+      peer->su_local = NULL;
+    }
+
+  if (peer->su_remote)
+    {
+      XFREE (MTYPE_SOCKUNION, peer->su_remote);
+      peer->su_remote = NULL;
+    }
+
+  /* Clear remote router-id. */
+  peer->remote_id.s_addr = 0;
+
+  /* Reset all negotiated variables */
+  peer->afc_nego[AFI_IP][SAFI_UNICAST] = 0;
+  peer->afc_nego[AFI_IP][SAFI_MULTICAST] = 0;
+  peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] = 0;
+  peer->afc_nego[AFI_IP6][SAFI_UNICAST] = 0;
+  peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = 0;
+  peer->afc_adv[AFI_IP][SAFI_UNICAST] = 0;
+  peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 0;
+  peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 0;
+  peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 0;
+  peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 0;
+  peer->afc_recv[AFI_IP][SAFI_UNICAST] = 0;
+  peer->afc_recv[AFI_IP][SAFI_MULTICAST] = 0;
+  peer->afc_recv[AFI_IP][SAFI_MPLS_VPN] = 0;
+  peer->afc_recv[AFI_IP6][SAFI_UNICAST] = 0;
+  peer->afc_recv[AFI_IP6][SAFI_MULTICAST] = 0;
+
+  /* Reset route refresh flag. */
+  UNSET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
+  UNSET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
+  UNSET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
+  UNSET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
+  UNSET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
+
+  for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
+    for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
+      {
+	/* peer address family capability flags*/
+	peer->af_cap[afi][safi] = 0;
+	/* peer address family status flags*/
+	peer->af_sflags[afi][safi] = 0;
+	/* Received ORF prefix-filter */
+	peer->orf_plist[afi][safi] = NULL;
+        /* ORF received prefix-filter pnt */
+        sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
+        prefix_bgp_orf_remove_all (orf_name);
+      }
+
+  /* Reset keepalive and holdtime */
+  if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
+    {
+      peer->v_keepalive = peer->keepalive;
+      peer->v_holdtime = peer->holdtime;
+    }
+  else
+    {
+      peer->v_keepalive = peer->bgp->default_keepalive;
+      peer->v_holdtime = peer->bgp->default_holdtime;
+    }
+
+  peer->update_time = 0;
+
+  /* Until we are sure that there is no problem about prefix count
+     this should be commented out.*/
+#if 0
+  /* Reset prefix count */
+  peer->pcount[AFI_IP][SAFI_UNICAST] = 0;
+  peer->pcount[AFI_IP][SAFI_MULTICAST] = 0;
+  peer->pcount[AFI_IP][SAFI_MPLS_VPN] = 0;
+  peer->pcount[AFI_IP6][SAFI_UNICAST] = 0;
+  peer->pcount[AFI_IP6][SAFI_MULTICAST] = 0;
+#endif /* 0 */
+
+  return 0;
+}
+
+/* BGP peer is stoped by the error. */
+int
+bgp_stop_with_error (struct peer *peer)
+{
+  /* Double start timer. */
+  peer->v_start *= 2;
+
+  /* Overflow check. */
+  if (peer->v_start >= (60 * 2))
+    peer->v_start = (60 * 2);
+
+  bgp_stop (peer);
+
+  return 0;
+}
+
+/* TCP connection open.  Next we send open message to remote peer. And
+   add read thread for reading open message. */
+int
+bgp_connect_success (struct peer *peer)
+{
+  if (peer->fd < 0)
+    {
+      zlog_err ("bgp_connect_success peer's fd is negative value %d",
+		peer->fd);
+      return -1;
+    }
+  BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
+
+  /* bgp_getsockname (peer); */
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
+    bgp_open_send (peer);
+
+  return 0;
+}
+
+/* TCP connect fail */
+int
+bgp_connect_fail (struct peer *peer)
+{
+  bgp_stop (peer);
+  return 0;
+}
+
+/* This function is the first starting point of all BGP connection. It
+   try to connect to remote peer with non-blocking IO. */
+int
+bgp_start (struct peer *peer)
+{
+  int status;
+
+  /* If the peer is passive mode, force to move to Active mode. */
+  if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
+    {
+      BGP_EVENT_ADD (peer, TCP_connection_open_failed);
+      return 0;
+    }
+
+  status = bgp_connect (peer);
+
+  switch (status)
+    {
+    case connect_error:
+      if (BGP_DEBUG (fsm, FSM))
+	plog_info (peer->log, "%s [FSM] Connect error", peer->host);
+      BGP_EVENT_ADD (peer, TCP_connection_open_failed);
+      break;
+    case connect_success:
+      if (BGP_DEBUG (fsm, FSM))
+	plog_info (peer->log, "%s [FSM] Connect immediately success",
+		   peer->host);
+      BGP_EVENT_ADD (peer, TCP_connection_open);
+      break;
+    case connect_in_progress:
+      /* To check nonblocking connect, we wait until socket is
+         readable or writable. */
+      if (BGP_DEBUG (fsm, FSM))
+	plog_info (peer->log, "%s [FSM] Non blocking connect waiting result",
+		   peer->host);
+      if (peer->fd < 0)
+	{
+	  zlog_err ("bgp_start peer's fd is negative value %d",
+		    peer->fd);
+	  return -1;
+	}
+      BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
+      BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+      break;
+    }
+  return 0;
+}
+
+/* Connect retry timer is expired when the peer status is Connect. */
+int
+bgp_reconnect (struct peer *peer)
+{
+  bgp_stop (peer);
+  bgp_start (peer);
+  return 0;
+}
+
+int
+bgp_fsm_open (struct peer *peer)
+{
+  /* Send keepalive and make keepalive timer */
+  bgp_keepalive_send (peer);
+
+  /* Reset holdtimer value. */
+  BGP_TIMER_OFF (peer->t_holdtime);
+
+  return 0;
+}
+
+/* Called after event occured, this function change status and reset
+   read/write and timer thread. */
+void
+bgp_fsm_change_status (struct peer *peer, int status)
+{
+  bgp_dump_state (peer, peer->status, status);
+
+  /* Preserve old status and change into new status. */
+  peer->ostatus = peer->status;
+  peer->status = status;
+}
+
+/* Keepalive send to peer. */
+int
+bgp_fsm_keepalive_expire (struct peer *peer)
+{
+  bgp_keepalive_send (peer);
+  return 0;
+}
+
+/* Hold timer expire.  This is error of BGP connection. So cut the
+   peer and change to Idle status. */
+int
+bgp_fsm_holdtime_expire (struct peer *peer)
+{
+  if (BGP_DEBUG (fsm, FSM))
+    zlog (peer->log, LOG_DEBUG, "%s [FSM] Hold timer expire", peer->host);
+
+  /* Send notify to remote peer. */
+  bgp_notify_send (peer, BGP_NOTIFY_HOLD_ERR, 0);
+
+  /* Sweep if it is temporary peer. */
+  if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
+    {
+      zlog_info ("%s [Event] Accepting BGP peer is deleted", peer->host);
+      peer_delete (peer);
+      return -1;
+    }
+
+  return 0;
+}
+
+/* Status goes to Established.  Send keepalive packet then make first
+   update information. */
+int
+bgp_establish (struct peer *peer)
+{
+  struct bgp_notify *notify;
+  afi_t afi;
+  safi_t safi;
+
+  /* Reset capability open status flag. */
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN))
+    SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
+
+  /* Clear last notification data. */
+  notify = &peer->notify;
+  if (notify->data)
+    XFREE (MTYPE_TMP, notify->data);
+  memset (notify, 0, sizeof (struct bgp_notify));
+
+  /* Clear start timer value to default. */
+  peer->v_start = BGP_INIT_START_TIMER;
+
+  /* Increment established count. */
+  peer->established++;
+  bgp_fsm_change_status (peer, Established);
+#ifdef HAVE_SNMP
+  bgpTrapEstablished (peer);
+#endif /* HAVE_SNMP */
+
+  /* Reset uptime, send keepalive, send current table. */
+  bgp_uptime_reset (peer);
+
+  /* Send route-refresh when ORF is enabled */
+  for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
+    for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
+      if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV))
+	{
+	  if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
+	    bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX,
+				    REFRESH_IMMEDIATE, 0);
+	  else if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
+	    bgp_route_refresh_send (peer, afi, safi, ORF_TYPE_PREFIX_OLD,
+				    REFRESH_IMMEDIATE, 0);
+	}
+
+  if (peer->v_keepalive)
+    bgp_keepalive_send (peer);
+
+  /* First update is deferred until ORF or ROUTE-REFRESH is received */
+  for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
+    for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
+      if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV))
+	if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
+	    || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV))
+	  SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
+
+  bgp_announce_route_all (peer);
+
+  BGP_TIMER_ON (peer->t_routeadv, bgp_routeadv_timer, 1);
+
+  return 0;
+}
+
+/* Keepalive packet is received. */
+int
+bgp_fsm_keepalive (struct peer *peer)
+{
+  /* peer count update */
+  peer->keepalive_in++;
+
+  BGP_TIMER_OFF (peer->t_holdtime);
+  return 0;
+}
+
+/* Update packet is received. */
+int
+bgp_fsm_update (struct peer *peer)
+{
+  BGP_TIMER_OFF (peer->t_holdtime);
+  return 0;
+}
+
+/* This is empty event. */
+int
+bgp_ignore (struct peer *peer)
+{
+  if (BGP_DEBUG (fsm, FSM))
+    zlog (peer->log, LOG_DEBUG, "%s [FSM] bgp_ignore called", peer->host);
+  return 0;
+}
+
+/* Finite State Machine structure */
+struct {
+  int (*func) ();
+  int next_state;
+} FSM [BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1] = 
+{
+  {
+    /* Idle state: In Idle state, all events other than BGP_Start is
+       ignored.  With BGP_Start event, finite state machine calls
+       bgp_start(). */
+    {bgp_start,  Connect},	/* BGP_Start                    */
+    {bgp_stop,   Idle},		/* BGP_Stop                     */
+    {bgp_stop,   Idle},		/* TCP_connection_open          */
+    {bgp_stop,   Idle},		/* TCP_connection_closed        */
+    {bgp_ignore, Idle},		/* TCP_connection_open_failed   */
+    {bgp_stop,   Idle},		/* TCP_fatal_error              */
+    {bgp_ignore, Idle},		/* ConnectRetry_timer_expired   */
+    {bgp_ignore, Idle},		/* Hold_Timer_expired           */
+    {bgp_ignore, Idle},		/* KeepAlive_timer_expired      */
+    {bgp_ignore, Idle},		/* Receive_OPEN_message         */
+    {bgp_ignore, Idle},		/* Receive_KEEPALIVE_message    */
+    {bgp_ignore, Idle},		/* Receive_UPDATE_message       */
+    {bgp_ignore, Idle},		/* Receive_NOTIFICATION_message */
+  },
+  {
+    /* Connect */
+    {bgp_ignore,  Connect},	/* BGP_Start                    */
+    {bgp_stop,    Idle},	/* BGP_Stop                     */
+    {bgp_connect_success, OpenSent}, /* TCP_connection_open          */
+    {bgp_stop, Idle},		/* TCP_connection_closed        */
+    {bgp_connect_fail, Active}, /* TCP_connection_open_failed   */
+    {bgp_connect_fail, Idle},	/* TCP_fatal_error              */
+    {bgp_reconnect, Connect},	/* ConnectRetry_timer_expired   */
+    {bgp_ignore,  Idle},	/* Hold_Timer_expired           */
+    {bgp_ignore,  Idle},	/* KeepAlive_timer_expired      */
+    {bgp_ignore,  Idle},	/* Receive_OPEN_message         */
+    {bgp_ignore,  Idle},	/* Receive_KEEPALIVE_message    */
+    {bgp_ignore,  Idle},	/* Receive_UPDATE_message       */
+    {bgp_stop,    Idle},	/* Receive_NOTIFICATION_message */
+  },
+  {
+    /* Active, */
+    {bgp_ignore,  Active},	/* BGP_Start                    */
+    {bgp_stop,    Idle},	/* BGP_Stop                     */
+    {bgp_connect_success, OpenSent}, /* TCP_connection_open          */
+    {bgp_stop,    Idle},	/* TCP_connection_closed        */
+    {bgp_ignore,  Active},	/* TCP_connection_open_failed   */
+    {bgp_ignore,  Idle},	/* TCP_fatal_error              */
+    {bgp_start,   Connect},	/* ConnectRetry_timer_expired   */
+    {bgp_ignore,  Idle},	/* Hold_Timer_expired           */
+    {bgp_ignore,  Idle},	/* KeepAlive_timer_expired      */
+    {bgp_ignore,  Idle},	/* Receive_OPEN_message         */
+    {bgp_ignore,  Idle},	/* Receive_KEEPALIVE_message    */
+    {bgp_ignore,  Idle},	/* Receive_UPDATE_message       */
+    {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
+  },
+  {
+    /* OpenSent, */
+    {bgp_ignore,  OpenSent},	/* BGP_Start                    */
+    {bgp_stop,    Idle},	/* BGP_Stop                     */
+    {bgp_stop,    Idle},	/* TCP_connection_open          */
+    {bgp_stop,    Active},	/* TCP_connection_closed        */
+    {bgp_ignore,  Idle},	/* TCP_connection_open_failed   */
+    {bgp_stop,    Idle},	/* TCP_fatal_error              */
+    {bgp_ignore,  Idle},	/* ConnectRetry_timer_expired   */
+    {bgp_fsm_holdtime_expire, Idle},	/* Hold_Timer_expired           */
+    {bgp_ignore,  Idle},	/* KeepAlive_timer_expired      */
+    {bgp_fsm_open,    OpenConfirm},	/* Receive_OPEN_message         */
+    {bgp_ignore,  Idle},	/* Receive_KEEPALIVE_message    */
+    {bgp_ignore,  Idle},	/* Receive_UPDATE_message       */
+    {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
+  },
+  {
+    /* OpenConfirm, */
+    {bgp_ignore,  OpenConfirm},	/* BGP_Start                    */
+    {bgp_stop,    Idle},	/* BGP_Stop                     */
+    {bgp_stop,    Idle},	/* TCP_connection_open          */
+    {bgp_stop,    Idle},	/* TCP_connection_closed        */
+    {bgp_stop,    Idle},	/* TCP_connection_open_failed   */
+    {bgp_stop,    Idle},	/* TCP_fatal_error              */
+    {bgp_ignore,  Idle},	/* ConnectRetry_timer_expired   */
+    {bgp_fsm_holdtime_expire, Idle},	/* Hold_Timer_expired           */
+    {bgp_ignore,  OpenConfirm},	/* KeepAlive_timer_expired      */
+    {bgp_ignore,  Idle},	/* Receive_OPEN_message         */
+    {bgp_establish, Established}, /* Receive_KEEPALIVE_message    */
+    {bgp_ignore,  Idle},	/* Receive_UPDATE_message       */
+    {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
+  },
+  {
+    /* Established, */
+    {bgp_ignore,  Established},	/* BGP_Start                    */
+    {bgp_stop,    Idle},	/* BGP_Stop                     */
+    {bgp_stop,    Idle},	/* TCP_connection_open          */
+    {bgp_stop,    Idle},	/* TCP_connection_closed        */
+    {bgp_ignore,  Idle},	/* TCP_connection_open_failed   */
+    {bgp_stop,    Idle},	/* TCP_fatal_error              */
+    {bgp_ignore,  Idle},	/* ConnectRetry_timer_expired   */
+    {bgp_fsm_holdtime_expire, Idle}, /* Hold_Timer_expired           */
+    {bgp_fsm_keepalive_expire, Established}, /* KeepAlive_timer_expired      */
+    {bgp_stop, Idle},		/* Receive_OPEN_message         */
+    {bgp_fsm_keepalive, Established}, /* Receive_KEEPALIVE_message    */
+    {bgp_fsm_update,   Established}, /* Receive_UPDATE_message       */
+    {bgp_stop_with_error, Idle}, /* Receive_NOTIFICATION_message */
+  },
+};
+
+static char *bgp_event_str[] =
+{
+  NULL,
+  "BGP_Start",
+  "BGP_Stop",
+  "TCP_connection_open",
+  "TCP_connection_closed",
+  "TCP_connection_open_failed",
+  "TCP_fatal_error",
+  "ConnectRetry_timer_expired",
+  "Hold_Timer_expired",
+  "KeepAlive_timer_expired",
+  "Receive_OPEN_message",
+  "Receive_KEEPALIVE_message",
+  "Receive_UPDATE_message",
+  "Receive_NOTIFICATION_message"
+};
+
+/* Execute event process. */
+int
+bgp_event (struct thread *thread)
+{
+  int ret;
+  int event;
+  int next;
+  struct peer *peer;
+
+  peer = THREAD_ARG (thread);
+  event = THREAD_VAL (thread);
+
+  /* Logging this event. */
+  next = FSM [peer->status -1][event - 1].next_state;
+
+  if (BGP_DEBUG (fsm, FSM))
+    plog_info (peer->log, "%s [FSM] %s (%s->%s)", peer->host, 
+	       bgp_event_str[event],
+	       LOOKUP (bgp_status_msg, peer->status),
+	       LOOKUP (bgp_status_msg, next));
+  if (BGP_DEBUG (normal, NORMAL)
+      && strcmp (LOOKUP (bgp_status_msg, peer->status), LOOKUP (bgp_status_msg, next)))
+    zlog_info ("%s went from %s to %s",
+	       peer->host,
+	       LOOKUP (bgp_status_msg, peer->status),
+	       LOOKUP (bgp_status_msg, next));
+
+  /* Call function. */
+  ret = (*(FSM [peer->status - 1][event - 1].func))(peer);
+
+  /* When function do not want proceed next job return -1. */
+  if (ret < 0)
+    return ret;
+    
+  /* If status is changed. */
+  if (next != peer->status)
+    bgp_fsm_change_status (peer, next);
+
+  /* Make sure timer is set. */
+  bgp_timer_set (peer);
+
+  return 0;
+}
diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h
new file mode 100644
index 0000000..f051aaa
--- /dev/null
+++ b/bgpd/bgp_fsm.h
@@ -0,0 +1,42 @@
+/* BGP-4 Finite State Machine   
+   From RFC1771 [A Border Gateway Protocol 4 (BGP-4)]
+   Copyright (C) 1998 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+/* Macro for BGP read, write and timer thread.  */
+#define BGP_READ_ON(T,F,V)   THREAD_READ_ON(master,T,F,peer,V)
+#define BGP_READ_OFF(X)      THREAD_READ_OFF(X)
+
+#define BGP_WRITE_ON(T,F,V)  THREAD_WRITE_ON(master,T,F,peer,V)
+#define BGP_WRITE_OFF(X)     THREAD_WRITE_OFF(X)
+
+#define BGP_TIMER_ON(T,F,V)  THREAD_TIMER_ON(master,T,F,peer,V)
+#define BGP_TIMER_OFF(X)     THREAD_TIMER_OFF(X)
+
+#define BGP_EVENT_ADD(P,E) \
+    thread_add_event (master, bgp_event, (P), (E))
+
+#define BGP_EVENT_DELETE(P) \
+    thread_cancel_event (master, (P))
+
+/* Prototypes. */
+int bgp_event (struct thread *);
+int bgp_stop (struct peer *peer);
+void bgp_timer_set (struct peer *);
+void bgp_fsm_change_status (struct peer *peer, int status);
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
new file mode 100644
index 0000000..7fc68fa
--- /dev/null
+++ b/bgpd/bgp_main.c
@@ -0,0 +1,285 @@
+/* Main routine of bgpd.
+   Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "vector.h"
+#include "vty.h"
+#include "command.h"
+#include "getopt.h"
+#include "thread.h"
+#include "version.h"
+#include "memory.h"
+#include "prefix.h"
+#include "log.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_mplsvpn.h"
+
+/* bgpd options, we use GNU getopt library. */
+struct option longopts[] = 
+{
+  { "daemon",      no_argument,       NULL, 'd'},
+  { "config_file", required_argument, NULL, 'f'},
+  { "pid_file",    required_argument, NULL, 'i'},
+  { "bgp_port",    required_argument, NULL, 'p'},
+  { "vty_addr",    required_argument, NULL, 'A'},
+  { "vty_port",    required_argument, NULL, 'P'},
+  { "retain",      no_argument,       NULL, 'r'},
+  { "no_kernel",   no_argument,       NULL, 'n'},
+  { "version",     no_argument,       NULL, 'v'},
+  { "help",        no_argument,       NULL, 'h'},
+  { 0 }
+};
+
+/* Configuration file and directory. */
+char config_current[] = BGP_DEFAULT_CONFIG;
+char config_default[] = SYSCONFDIR BGP_DEFAULT_CONFIG;
+
+/* Route retain mode flag. */
+int retain_mode = 0;
+
+/* Master of threads. */
+struct thread_master *master;
+
+/* Manually specified configuration file name.  */
+char *config_file = NULL;
+
+/* Process ID saved for use by init system */
+char *pid_file = PATH_BGPD_PID;
+
+/* VTY port number and address.  */
+int vty_port = BGP_VTY_PORT;
+char *vty_addr = NULL;
+
+/* Help information display. */
+static void
+usage (char *progname, int status)
+{
+  if (status != 0)
+    fprintf (stderr, "Try `%s --help' for more information.\n", progname);
+  else
+    {    
+      printf ("Usage : %s [OPTION...]\n\n\
+Daemon which manages kernel routing table management and \
+redistribution between different routing protocols.\n\n\
+-d, --daemon       Runs in daemon mode\n\
+-f, --config_file  Set configuration file name\n\
+-i, --pid_file     Set process identifier file name\n\
+-p, --bgp_port     Set bgp protocol's port number\n\
+-A, --vty_addr     Set vty's bind address\n\
+-P, --vty_port     Set vty's port number\n\
+-r, --retain       When program terminates, retain added route by bgpd.\n\
+-n, --no_kernel    Do not install route to kernel.\n\
+-v, --version      Print program version\n\
+-h, --help         Display this help and exit\n\
+\n\
+Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
+    }
+
+  exit (status);
+}
+
+/* SIGHUP handler. */
+void 
+sighup (int sig)
+{
+  zlog (NULL, LOG_INFO, "SIGHUP received");
+
+  /* Terminate all thread. */
+  bgp_terminate ();
+  bgp_reset ();
+  zlog_info ("bgpd restarting!");
+
+  /* Reload config file. */
+  vty_read_config (config_file, config_current, config_default);
+
+  /* Create VTY's socket */
+  vty_serv_sock (vty_addr, vty_port ? vty_port : BGP_VTY_PORT, BGP_VTYSH_PATH);
+
+  /* Try to return to normal operation. */
+}
+
+/* SIGINT handler. */
+void
+sigint (int sig)
+{
+  zlog (NULL, LOG_INFO, "Terminating on signal");
+
+  if (! retain_mode)
+    bgp_terminate ();
+
+  exit (0);
+}
+
+/* SIGUSR1 handler. */
+void
+sigusr1 (int sig)
+{
+  zlog_rotate (NULL);
+}
+
+/* Signale wrapper. */
+RETSIGTYPE *
+signal_set (int signo, void (*func)(int))
+{
+  int ret;
+  struct sigaction sig;
+  struct sigaction osig;
+
+  sig.sa_handler = func;
+  sigemptyset (&sig.sa_mask);
+  sig.sa_flags = 0;
+#ifdef SA_RESTART
+  sig.sa_flags |= SA_RESTART;
+#endif /* SA_RESTART */
+
+  ret = sigaction (signo, &sig, &osig);
+
+  if (ret < 0) 
+    return (SIG_ERR);
+  else
+    return (osig.sa_handler);
+}
+
+/* Initialization of signal handles. */
+void
+signal_init ()
+{
+  signal_set (SIGHUP, sighup);
+  signal_set (SIGINT, sigint);
+  signal_set (SIGTERM, sigint);
+  signal_set (SIGPIPE, SIG_IGN);
+  signal_set (SIGUSR1, sigusr1);
+}
+
+/* Main routine of bgpd. Treatment of argument and start bgp finite
+   state machine is handled at here. */
+int
+main (int argc, char **argv)
+{
+  char *p;
+  int opt;
+  int daemon_mode = 0;
+  char *progname;
+  struct thread thread;
+
+  /* Set umask before anything for security */
+  umask (0027);
+
+  /* Preserve name of myself. */
+  progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);
+
+  zlog_default = openzlog (progname, ZLOG_NOLOG, ZLOG_BGP,
+			   LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
+
+  /* BGP master init. */
+  bgp_master_init ();
+
+  /* Command line argument treatment. */
+  while (1) 
+    {
+      opt = getopt_long (argc, argv, "df:hp:A:P:rnv", longopts, 0);
+    
+      if (opt == EOF)
+	break;
+
+      switch (opt) 
+	{
+	case 0:
+	  break;
+	case 'd':
+	  daemon_mode = 1;
+	  break;
+	case 'f':
+	  config_file = optarg;
+	  break;
+        case 'i':
+          pid_file = optarg;
+          break;
+	case 'p':
+	  bm->port = atoi (optarg);
+	  break;
+	case 'A':
+	  vty_addr = optarg;
+	  break;
+	case 'P':
+	  vty_port = atoi (optarg);
+	  break;
+	case 'r':
+	  retain_mode = 1;
+	  break;
+	case 'n':
+	  bgp_option_set (BGP_OPT_NO_FIB);
+	  break;
+	case 'v':
+	  print_version (progname);
+	  exit (0);
+	  break;
+	case 'h':
+	  usage (progname, 0);
+	  break;
+	default:
+	  usage (progname, 1);
+	  break;
+	}
+    }
+
+  /* Make thread master. */
+  master = bm->master;
+
+  /* Initializations. */
+  srand (time (NULL));
+  signal_init ();
+  cmd_init (1);
+  vty_init ();
+  memory_init ();
+
+  /* BGP related initialization.  */
+  bgp_init ();
+
+  /* Sort CLI commands. */
+  sort_node ();
+
+  /* Parse config file. */
+  vty_read_config (config_file, config_current, config_default);
+
+  /* Turn into daemon if daemon_mode is set. */
+  if (daemon_mode)
+    daemon (0, 0);
+
+  /* Process ID file creation. */
+  pid_output (pid_file);
+
+  /* Make bgp vty socket. */
+  vty_serv_sock (vty_addr, vty_port, BGP_VTYSH_PATH);
+
+  /* Print banner. */
+  zlog_info ("BGPd %s starting: vty@%d, bgp@%d", ZEBRA_VERSION,
+	     vty_port, bm->port);
+
+  /* Start finite state machine, here we go! */
+  while (thread_fetch (master, &thread))
+    thread_call (&thread);
+
+  /* Not reached. */
+  exit (0);
+}
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
new file mode 100644
index 0000000..e820cab
--- /dev/null
+++ b/bgpd/bgp_mplsvpn.c
@@ -0,0 +1,741 @@
+/* MPLS-VPN
+   Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "command.h"
+#include "prefix.h"
+#include "log.h"
+#include "memory.h"
+#include "stream.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_table.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_mplsvpn.h"
+
+int route_vty_out (struct vty *, struct prefix *, struct bgp_info *, int, safi_t);
+int route_vty_out_tag (struct vty *, struct prefix *, struct bgp_info *, int, safi_t);
+void route_vty_out_tmp (struct vty *, struct prefix *, struct attr *, safi_t);
+
+u_int16_t
+decode_rd_type (u_char *pnt)
+{
+  u_int16_t v;
+  
+  v = ((u_int16_t) *pnt++ << 8);
+  v |= (u_int16_t) *pnt;
+  return v;
+}
+
+u_int32_t
+decode_label (u_char *pnt)
+{
+  u_int32_t l;
+
+  l = ((u_int32_t) *pnt++ << 12);
+  l |= (u_int32_t) *pnt++ << 4;
+  l |= (u_int32_t) ((*pnt & 0xf0) >> 4);
+  return l;
+}
+
+void
+decode_rd_as (u_char *pnt, struct rd_as *rd_as)
+{
+  rd_as->as = (u_int16_t) *pnt++ << 8;
+  rd_as->as |= (u_int16_t) *pnt++;
+  
+  rd_as->val = ((u_int32_t) *pnt++ << 24);
+  rd_as->val |= ((u_int32_t) *pnt++ << 16);
+  rd_as->val |= ((u_int32_t) *pnt++ << 8);
+  rd_as->val |= (u_int32_t) *pnt;
+}
+
+void
+decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip)
+{
+  memcpy (&rd_ip->ip, pnt, 4);
+  pnt += 4;
+  
+  rd_ip->val = ((u_int16_t) *pnt++ << 8);
+  rd_ip->val |= (u_int16_t) *pnt;
+}
+
+int bgp_update (struct peer *, struct prefix *, struct attr *, 
+		afi_t, safi_t, int, int, struct prefix_rd *, u_char *);
+
+int bgp_withdraw (struct peer *, struct prefix *, struct attr *, 
+		  int, int, int, int, struct prefix_rd *, u_char *);
+int
+bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr, 
+		      struct bgp_nlri *packet)
+{
+  u_char *pnt;
+  u_char *lim;
+  struct prefix p;
+  int psize;
+  int prefixlen;
+  u_int32_t label;
+  u_int16_t type;
+  struct rd_as rd_as;
+  struct rd_ip rd_ip;
+  struct prefix_rd prd;
+  u_char *tagpnt;
+
+  /* Check peer status. */
+  if (peer->status != Established)
+    return 0;
+  
+  /* Make prefix_rd */
+  prd.family = AF_UNSPEC;
+  prd.prefixlen = 64;
+
+  pnt = packet->nlri;
+  lim = pnt + packet->length;
+
+  for (; pnt < lim; pnt += psize)
+    {
+      /* Clear prefix structure. */
+      memset (&p, 0, sizeof (struct prefix));
+
+      /* Fetch prefix length. */
+      prefixlen = *pnt++;
+      p.family = AF_INET;
+      psize = PSIZE (prefixlen);
+
+      if (prefixlen < 88)
+	{
+	  zlog_err ("prefix length is less than 88: %d", prefixlen);
+	  return -1;
+	}
+
+      label = decode_label (pnt);
+
+      /* Copyr label to prefix. */
+      tagpnt = pnt;;
+
+      /* Copy routing distinguisher to rd. */
+      memcpy (&prd.val, pnt + 3, 8);
+
+      /* Decode RD type. */
+      type = decode_rd_type (pnt + 3);
+
+      /* Decode RD value. */
+      if (type == RD_TYPE_AS)
+	decode_rd_as (pnt + 5, &rd_as);
+      else if (type == RD_TYPE_IP)
+	decode_rd_ip (pnt + 5, &rd_ip);
+      else
+	{
+	  zlog_err ("Invalid RD type %d", type);
+	  return -1;
+	}
+
+      p.prefixlen = prefixlen - 88;
+      memcpy (&p.u.prefix, pnt + 11, psize - 11);
+
+#if 0
+      if (type == RD_TYPE_AS)
+	zlog_info ("prefix %ld:%ld:%ld:%s/%d", label, rd_as.as, rd_as.val,
+		   inet_ntoa (p.u.prefix4), p.prefixlen);
+      else if (type == RD_TYPE_IP)
+	zlog_info ("prefix %ld:%s:%ld:%s/%d", label, inet_ntoa (rd_ip.ip),
+		   rd_ip.val, inet_ntoa (p.u.prefix4), p.prefixlen);
+#endif /* 0 */
+
+      if (pnt + psize > lim)
+	return -1;
+
+      if (attr)
+	bgp_update (peer, &p, attr, AFI_IP, SAFI_MPLS_VPN,
+		    ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt);
+      else
+	bgp_withdraw (peer, &p, attr, AFI_IP, SAFI_MPLS_VPN,
+		      ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt);
+    }
+
+  /* Packet length consistency check. */
+  if (pnt != lim)
+    return -1;
+
+  return 0;
+}
+
+int
+str2prefix_rd (u_char *str, struct prefix_rd *prd)
+{
+  int ret;
+  u_char *p;
+  u_char *p2;
+  struct stream *s;
+  u_char *half;
+  struct in_addr addr;
+
+  s = stream_new (8);
+
+  prd->family = AF_UNSPEC;
+  prd->prefixlen = 64;
+
+  p = strchr (str, ':');
+  if (! p)
+    return 0;
+
+  if (! all_digit (p + 1))
+    return 0;
+
+  half = XMALLOC (MTYPE_TMP, (p - str) + 1);
+  memcpy (half, str, (p - str));
+  half[p - str] = '\0';
+
+  p2 = strchr (str, '.');
+
+  if (! p2)
+    {
+      if (! all_digit (half))
+	{
+	  XFREE (MTYPE_TMP, half);
+	  return 0;
+	}
+      stream_putw (s, RD_TYPE_AS);
+      stream_putw (s, atoi (half));
+      stream_putl (s, atol (p + 1));
+    }
+  else
+    {
+      ret = inet_aton (half, &addr);
+      if (! ret)
+	{
+	  XFREE (MTYPE_TMP, half);
+	  return 0;
+	}
+      stream_putw (s, RD_TYPE_IP);
+      stream_put_in_addr (s, &addr);
+      stream_putw (s, atol (p + 1));
+    }
+  memcpy (prd->val, s->data, 8);
+
+  return 1;
+}
+
+int
+str2tag (u_char *str, u_char *tag)
+{
+  u_int32_t l;
+
+  l = atol (str);
+
+  tag[0] = (u_char)(l >> 12);
+  tag[1] = (u_char)(l >> 4);
+  tag[2] = (u_char)(l << 4);
+
+  return 1;
+}
+
+char *
+prefix_rd2str (struct prefix_rd *prd, char *buf, size_t size)
+{
+  u_char *pnt;
+  u_int16_t type;
+  struct rd_as rd_as;
+  struct rd_ip rd_ip;
+
+  if (size < RD_ADDRSTRLEN)
+    return NULL;
+
+  pnt = prd->val;
+
+  type = decode_rd_type (pnt);
+
+  if (type == RD_TYPE_AS)
+    {
+      decode_rd_as (pnt + 2, &rd_as);
+      snprintf (buf, size, "%d:%d", rd_as.as, rd_as.val);
+      return buf;
+    }
+  else if (type == RD_TYPE_IP)
+    {
+      decode_rd_ip (pnt + 2, &rd_ip);
+      snprintf (buf, size, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
+      return buf;
+    }
+
+  return NULL;
+}
+
+/* For testing purpose, static route of MPLS-VPN. */
+DEFUN (vpnv4_network,
+       vpnv4_network_cmd,
+       "network A.B.C.D/M rd ASN:nn_or_IP-address:nn tag WORD",
+       "Specify a network to announce via BGP\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+       "Specify Route Distinguisher\n"
+       "VPN Route Distinguisher\n"
+       "BGP tag\n"
+       "tag value\n")
+{
+  return bgp_static_set_vpnv4 (vty, argv[0], argv[1], argv[2]);
+}
+
+/* For testing purpose, static route of MPLS-VPN. */
+DEFUN (no_vpnv4_network,
+       no_vpnv4_network_cmd,
+       "no network A.B.C.D/M rd ASN:nn_or_IP-address:nn tag WORD",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+       "Specify Route Distinguisher\n"
+       "VPN Route Distinguisher\n"
+       "BGP tag\n"
+       "tag value\n")
+{
+  return bgp_static_unset_vpnv4 (vty, argv[0], argv[1], argv[2]);
+}
+
+int
+show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd)
+{
+  struct bgp *bgp;
+  struct bgp_table *table;
+  struct bgp_node *rn;
+  struct bgp_node *rm;
+  struct attr *attr;
+  int rd_header;
+  int header = 1;
+  char v4_header[] = "   Network          Next Hop            Metric LocPrf Weight Path%s";
+
+  bgp = bgp_get_default ();
+  if (bgp == NULL)
+    {
+      vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  for (rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_MPLS_VPN]); rn;
+       rn = bgp_route_next (rn))
+    {
+      if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
+        continue;
+
+      if ((table = rn->info) != NULL)
+        {
+          rd_header = 1;
+
+          for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm))
+            if ((attr = rm->info) != NULL)
+              {
+                if (header)
+                  {
+                    vty_out (vty, "BGP table version is 0, local router ID is %s%s",
+                             inet_ntoa (bgp->router_id), VTY_NEWLINE);
+                    vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s",
+                             VTY_NEWLINE);
+                    vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s",
+                             VTY_NEWLINE, VTY_NEWLINE);
+                    vty_out (vty, v4_header, VTY_NEWLINE);
+                    header = 0;
+                  }
+
+                if (rd_header)
+                  {
+                    u_int16_t type;
+                    struct rd_as rd_as;
+                    struct rd_ip rd_ip;
+                    u_char *pnt;
+
+                    pnt = rn->p.u.val;
+
+                    /* Decode RD type. */
+                    type = decode_rd_type (pnt);
+                    /* Decode RD value. */
+                    if (type == RD_TYPE_AS)
+                      decode_rd_as (pnt + 2, &rd_as);
+                    else if (type == RD_TYPE_IP)
+                      decode_rd_ip (pnt + 2, &rd_ip);
+
+                    vty_out (vty, "Route Distinguisher: ");
+
+                    if (type == RD_TYPE_AS)
+                      vty_out (vty, "%d:%d", rd_as.as, rd_as.val);
+                    else if (type == RD_TYPE_IP)
+                      vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
+
+                    vty_out (vty, "%s", VTY_NEWLINE);
+                    rd_header = 0;
+                  }
+                route_vty_out_tmp (vty, &rm->p, attr, SAFI_MPLS_VPN);
+              }
+        }
+    }
+  return CMD_SUCCESS;
+}
+
+enum bgp_show_type
+{
+  bgp_show_type_normal,
+  bgp_show_type_regexp,
+  bgp_show_type_prefix_list,
+  bgp_show_type_filter_list,
+  bgp_show_type_neighbor,
+  bgp_show_type_cidr_only,
+  bgp_show_type_prefix_longer,
+  bgp_show_type_community_all,
+  bgp_show_type_community,
+  bgp_show_type_community_exact,
+  bgp_show_type_community_list,
+  bgp_show_type_community_list_exact
+};
+
+int
+bgp_show_mpls_vpn (struct vty *vty, struct prefix_rd *prd, enum bgp_show_type type,
+		   void *output_arg, int tags)
+{
+  struct bgp *bgp;
+  struct bgp_table *table;
+  struct bgp_node *rn;
+  struct bgp_node *rm;
+  struct bgp_info *ri;
+  int rd_header;
+  int header = 1;
+  char v4_header[] = "   Network          Next Hop            Metric LocPrf Weight Path%s";
+  char v4_header_tag[] = "   Network          Next Hop      In tag/Out tag%s";
+
+  bgp = bgp_get_default ();
+  if (bgp == NULL)
+    {
+      vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  
+  for (rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_MPLS_VPN]); rn; rn = bgp_route_next (rn))
+    {
+      if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
+	continue;
+
+      if ((table = rn->info) != NULL)
+	{
+	  rd_header = 1;
+
+	  for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm))
+	    for (ri = rm->info; ri; ri = ri->next)
+	      {
+		if (type == bgp_show_type_neighbor)
+		  {
+		    union sockunion *su = output_arg;
+
+		    if (ri->peer->su_remote == NULL || ! sockunion_same(ri->peer->su_remote, su))
+		      continue;
+		  }
+		if (header)
+		  {
+		    if (tags)
+		      vty_out (vty, v4_header_tag, VTY_NEWLINE);
+		    else
+		      {
+			vty_out (vty, "BGP table version is 0, local router ID is %s%s",
+				 inet_ntoa (bgp->router_id), VTY_NEWLINE);
+			vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s",
+				 VTY_NEWLINE);
+			vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s",
+				 VTY_NEWLINE, VTY_NEWLINE);
+			vty_out (vty, v4_header, VTY_NEWLINE);
+		      }
+		    header = 0;
+		  }
+
+		if (rd_header)
+		  {
+		    u_int16_t type;
+		    struct rd_as rd_as;
+		    struct rd_ip rd_ip;
+		    u_char *pnt;
+
+		    pnt = rn->p.u.val;
+
+		    /* Decode RD type. */
+		    type = decode_rd_type (pnt);
+		    /* Decode RD value. */
+		    if (type == RD_TYPE_AS)
+		      decode_rd_as (pnt + 2, &rd_as);
+		    else if (type == RD_TYPE_IP)
+		      decode_rd_ip (pnt + 2, &rd_ip);
+
+		    vty_out (vty, "Route Distinguisher: ");
+
+		    if (type == RD_TYPE_AS)
+		      vty_out (vty, "%d:%d", rd_as.as, rd_as.val);
+		    else if (type == RD_TYPE_IP)
+		      vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
+		  
+		    vty_out (vty, "%s", VTY_NEWLINE);		  
+		    rd_header = 0;
+		  }
+	        if (tags)
+		  route_vty_out_tag (vty, &rm->p, ri, 0, SAFI_MPLS_VPN);
+	        else
+		  route_vty_out (vty, &rm->p, ri, 0, SAFI_MPLS_VPN);
+	      }
+        }
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_bgp_vpnv4_all,
+       show_ip_bgp_vpnv4_all_cmd,
+       "show ip bgp vpnv4 all",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display VPNv4 NLRI specific information\n"
+       "Display information about all VPNv4 NLRIs\n")
+{
+  return bgp_show_mpls_vpn (vty, NULL, bgp_show_type_normal, NULL, 0);
+}
+
+DEFUN (show_ip_bgp_vpnv4_rd,
+       show_ip_bgp_vpnv4_rd_cmd,
+       "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display VPNv4 NLRI specific information\n"
+       "Display information for a route distinguisher\n"
+       "VPN Route Distinguisher\n")
+{
+  int ret;
+  struct prefix_rd prd;
+
+  ret = str2prefix_rd (argv[0], &prd);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  return bgp_show_mpls_vpn (vty, &prd, bgp_show_type_normal, NULL, 0);
+}
+
+DEFUN (show_ip_bgp_vpnv4_all_tags,
+       show_ip_bgp_vpnv4_all_tags_cmd,
+       "show ip bgp vpnv4 all tags",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display VPNv4 NLRI specific information\n"
+       "Display information about all VPNv4 NLRIs\n"
+       "Display BGP tags for prefixes\n")
+{
+  return bgp_show_mpls_vpn (vty, NULL, bgp_show_type_normal, NULL,  1);
+}
+
+DEFUN (show_ip_bgp_vpnv4_rd_tags,
+       show_ip_bgp_vpnv4_rd_tags_cmd,
+       "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn tags",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display VPNv4 NLRI specific information\n"
+       "Display information for a route distinguisher\n"
+       "VPN Route Distinguisher\n"
+       "Display BGP tags for prefixes\n")
+{
+  int ret;
+  struct prefix_rd prd;
+
+  ret = str2prefix_rd (argv[0], &prd);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  return bgp_show_mpls_vpn (vty, &prd, bgp_show_type_normal, NULL, 1);
+}
+
+DEFUN (show_ip_bgp_vpnv4_all_neighbor_routes,
+       show_ip_bgp_vpnv4_all_neighbor_routes_cmd,
+       "show ip bgp vpnv4 all neighbors A.B.C.D routes",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display VPNv4 NLRI specific information\n"
+       "Display information about all VPNv4 NLRIs\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Display routes learned from neighbor\n")
+{
+  union sockunion *su;
+  struct peer *peer;
+  
+  su = sockunion_str2su (argv[0]);
+  if (su == NULL)
+    {
+      vty_out (vty, "Malformed address: %s%s", argv[0], VTY_NEWLINE);
+               return CMD_WARNING;
+    }
+
+  peer = peer_lookup (NULL, su);
+  if (! peer || ! peer->afc[AFI_IP][SAFI_MPLS_VPN])
+    {
+      vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_show_mpls_vpn (vty, NULL, bgp_show_type_neighbor, su, 0);
+}
+
+DEFUN (show_ip_bgp_vpnv4_rd_neighbor_routes,
+       show_ip_bgp_vpnv4_rd_neighbor_routes_cmd,
+       "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn neighbors A.B.C.D routes",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display VPNv4 NLRI specific information\n"
+       "Display information for a route distinguisher\n"
+       "VPN Route Distinguisher\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Display routes learned from neighbor\n")
+{
+  int ret;
+  union sockunion *su;
+  struct peer *peer;
+  struct prefix_rd prd;
+
+  ret = str2prefix_rd (argv[0], &prd);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  su = sockunion_str2su (argv[1]);
+  if (su == NULL)
+    {
+      vty_out (vty, "Malformed address: %s%s", argv[0], VTY_NEWLINE);
+               return CMD_WARNING;
+    }
+
+  peer = peer_lookup (NULL, su);
+  if (! peer || ! peer->afc[AFI_IP][SAFI_MPLS_VPN])
+    {
+      vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_show_mpls_vpn (vty, &prd, bgp_show_type_neighbor, su, 0);
+}
+
+DEFUN (show_ip_bgp_vpnv4_all_neighbor_advertised_routes,
+       show_ip_bgp_vpnv4_all_neighbor_advertised_routes_cmd,
+       "show ip bgp vpnv4 all neighbors A.B.C.D advertised-routes",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display VPNv4 NLRI specific information\n"
+       "Display information about all VPNv4 NLRIs\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Display the routes advertised to a BGP neighbor\n")
+{
+  int ret;
+  struct peer *peer;
+  union sockunion su;
+
+  ret = str2sockunion (argv[0], &su);
+  if (ret < 0)
+    {
+      vty_out (vty, "%% Malformed address: %s%s", argv[0], VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  peer = peer_lookup (NULL, &su);
+  if (! peer || ! peer->afc[AFI_IP][SAFI_MPLS_VPN])
+    {
+      vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return show_adj_route_vpn (vty, peer, NULL);
+}
+
+DEFUN (show_ip_bgp_vpnv4_rd_neighbor_advertised_routes,
+       show_ip_bgp_vpnv4_rd_neighbor_advertised_routes_cmd,
+       "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn neighbors A.B.C.D advertised-routes",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display VPNv4 NLRI specific information\n"
+       "Display information for a route distinguisher\n"
+       "VPN Route Distinguisher\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Display the routes advertised to a BGP neighbor\n")
+{
+  int ret;
+  struct peer *peer;
+  struct prefix_rd prd;
+  union sockunion su;
+
+  ret = str2sockunion (argv[1], &su);
+  if (ret < 0)
+    {
+      vty_out (vty, "%% Malformed address: %s%s", argv[0], VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  peer = peer_lookup (NULL, &su);
+  if (! peer || ! peer->afc[AFI_IP][SAFI_MPLS_VPN])
+    {
+      vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ret = str2prefix_rd (argv[0], &prd);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return show_adj_route_vpn (vty, peer, &prd);
+}
+
+void
+bgp_mplsvpn_init ()
+{
+  install_element (BGP_VPNV4_NODE, &vpnv4_network_cmd);
+  install_element (BGP_VPNV4_NODE, &no_vpnv4_network_cmd);
+
+
+  install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_tags_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_tags_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_neighbor_routes_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_neighbor_routes_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_neighbor_advertised_routes_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_neighbor_advertised_routes_cmd);
+
+  install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_tags_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_tags_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_neighbor_routes_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_neighbor_routes_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_neighbor_advertised_routes_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_neighbor_advertised_routes_cmd);
+}
diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h
new file mode 100644
index 0000000..cd861a8
--- /dev/null
+++ b/bgpd/bgp_mplsvpn.h
@@ -0,0 +1,45 @@
+/* MPLS-VPN
+   Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#define RD_TYPE_AS      0
+#define RD_TYPE_IP      1
+
+#define RD_ADDRSTRLEN  28
+
+struct rd_as
+{
+  u_int16_t type;
+  as_t as;
+  u_int32_t val;
+};
+
+struct rd_ip
+{
+  u_int16_t type;
+  struct in_addr ip;
+  u_int16_t val;
+};
+
+void bgp_mplsvpn_init ();
+int bgp_nlri_parse_vpnv4 (struct peer *, struct attr *, struct bgp_nlri *);
+u_int32_t decode_label (u_char *);
+int str2prefix_rd (u_char *, struct prefix_rd *);
+int str2tag (u_char *, u_char *);
+char *prefix_rd2str (struct prefix_rd *, char *, size_t);
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
new file mode 100644
index 0000000..40e9cdb
--- /dev/null
+++ b/bgpd/bgp_network.c
@@ -0,0 +1,381 @@
+/* BGP network related fucntions
+   Copyright (C) 1999 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "thread.h"
+#include "sockunion.h"
+#include "memory.h"
+#include "log.h"
+#include "if.h"
+#include "prefix.h"
+#include "command.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_fsm.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_network.h"
+
+/* Accept bgp connection. */
+static int
+bgp_accept (struct thread *thread)
+{
+  int bgp_sock;
+  int accept_sock;
+  union sockunion su;
+  struct peer *peer;
+  struct peer *peer1;
+  struct bgp *bgp;
+  char buf[SU_ADDRSTRLEN];
+
+  /* Regiser accept thread. */
+  accept_sock = THREAD_FD (thread);
+  bgp = THREAD_ARG (thread);
+
+  if (accept_sock < 0)
+    {
+      zlog_err ("accept_sock is nevative value %d", accept_sock);
+      return -1;
+    }
+  thread_add_read (master, bgp_accept, bgp, accept_sock);
+
+  /* Accept client connection. */
+  bgp_sock = sockunion_accept (accept_sock, &su);
+  if (bgp_sock < 0)
+    {
+      zlog_err ("[Error] BGP socket accept failed (%s)", strerror (errno));
+      return -1;
+    }
+
+  if (BGP_DEBUG (events, EVENTS))
+    zlog_info ("[Event] BGP connection from host %s", inet_sutop (&su, buf));
+  
+  /* Check remote IP address */
+  peer1 = peer_lookup (bgp, &su);
+  if (! peer1 || peer1->status == Idle)
+    {
+      if (BGP_DEBUG (events, EVENTS))
+	{
+	  if (! peer1)
+	    zlog_info ("[Event] BGP connection IP address %s is not configured",
+		       inet_sutop (&su, buf));
+	  else
+	    zlog_info ("[Event] BGP connection IP address %s is Idle state",
+		       inet_sutop (&su, buf));
+	}
+      close (bgp_sock);
+      return -1;
+    }
+
+  /* In case of peer is EBGP, we should set TTL for this connection.  */
+  if (peer_sort (peer1) == BGP_PEER_EBGP)
+    sockopt_ttl (peer1->su.sa.sa_family, bgp_sock, peer1->ttl);
+
+  if (! bgp)
+    bgp = peer1->bgp;
+
+  /* Make dummy peer until read Open packet. */
+  if (BGP_DEBUG (events, EVENTS))
+    zlog_info ("[Event] Make dummy peer structure until read Open packet");
+
+  {
+    char buf[SU_ADDRSTRLEN + 1];
+
+    peer = peer_create_accept (bgp);
+    SET_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER);
+    peer->su = su;
+    peer->fd = bgp_sock;
+    peer->status = Active;
+    peer->local_id = peer1->local_id;
+
+    /* Make peer's address string. */
+    sockunion2str (&su, buf, SU_ADDRSTRLEN);
+    peer->host = strdup (buf);
+  }
+
+  BGP_EVENT_ADD (peer, TCP_connection_open);
+
+  return 0;
+}
+
+/* BGP socket bind. */
+int
+bgp_bind (struct peer *peer)
+{
+#ifdef SO_BINDTODEVICE
+  int ret;
+  struct ifreq ifreq;
+
+  if (! peer->ifname)
+    return 0;
+
+  strncpy ((char *)&ifreq.ifr_name, peer->ifname, sizeof (ifreq.ifr_name));
+
+  ret = setsockopt (peer->fd, SOL_SOCKET, SO_BINDTODEVICE, 
+		    &ifreq, sizeof (ifreq));
+  if (ret < 0)
+    {
+      zlog (peer->log, LOG_INFO, "bind to interface %s failed", peer->ifname);
+      return ret;
+    }
+#endif /* SO_BINDTODEVICE */
+  return 0;
+}
+
+int
+bgp_bind_address (int sock, struct in_addr *addr)
+{
+  int ret;
+  struct sockaddr_in local;
+
+  memset (&local, 0, sizeof (struct sockaddr_in));
+  local.sin_family = AF_INET;
+#ifdef HAVE_SIN_LEN
+  local.sin_len = sizeof(struct sockaddr_in);
+#endif /* HAVE_SIN_LEN */
+  memcpy (&local.sin_addr, addr, sizeof (struct in_addr));
+
+  ret = bind (sock, (struct sockaddr *)&local, sizeof (struct sockaddr_in));
+  if (ret < 0)
+    ;
+  return 0;
+}
+
+struct in_addr *
+bgp_update_address (struct interface *ifp)
+{
+  struct prefix_ipv4 *p;
+  struct connected *connected;
+  listnode node;
+
+  for (node = listhead (ifp->connected); node; nextnode (node))
+    {
+      connected = getdata (node);
+
+      p = (struct prefix_ipv4 *) connected->address;
+
+      if (p->family == AF_INET)
+	return &p->prefix;
+    }
+  return NULL;
+}
+
+/* Update source selection.  */
+void
+bgp_update_source (struct peer *peer)
+{
+  struct interface *ifp;
+  struct in_addr *addr;
+
+  /* Source is specified with interface name.  */
+  if (peer->update_if)
+    {
+      ifp = if_lookup_by_name (peer->update_if);
+      if (! ifp)
+	return;
+
+      addr = bgp_update_address (ifp);
+      if (! addr)
+	return;
+
+      bgp_bind_address (peer->fd, addr);
+    }
+
+  /* Source is specified with IP address.  */
+  if (peer->update_source)
+    sockunion_bind (peer->fd, peer->update_source, 0, peer->update_source);
+}
+
+/* BGP try to connect to the peer.  */
+int
+bgp_connect (struct peer *peer)
+{
+  unsigned int ifindex = 0;
+
+  /* Make socket for the peer. */
+  peer->fd = sockunion_socket (&peer->su);
+  if (peer->fd < 0)
+    return -1;
+
+  /* If we can get socket for the peer, adjest TTL and make connection. */
+  if (peer_sort (peer) == BGP_PEER_EBGP)
+    sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
+
+  sockopt_reuseaddr (peer->fd);
+  sockopt_reuseport (peer->fd);
+
+  /* Bind socket. */
+  bgp_bind (peer);
+
+  /* Update source bind. */
+  bgp_update_source (peer);
+
+#ifdef HAVE_IPV6
+  if (peer->ifname)
+    ifindex = if_nametoindex (peer->ifname);
+#endif /* HAVE_IPV6 */
+
+  if (BGP_DEBUG (events, EVENTS))
+    plog_info (peer->log, "%s [Event] Connect start to %s fd %d",
+	       peer->host, peer->host, peer->fd);
+
+  /* Connect to the remote peer. */
+  return sockunion_connect (peer->fd, &peer->su, htons (peer->port), ifindex);
+}
+
+/* After TCP connection is established.  Get local address and port. */
+void
+bgp_getsockname (struct peer *peer)
+{
+  if (peer->su_local)
+    {
+      XFREE (MTYPE_TMP, peer->su_local);
+      peer->su_local = NULL;
+    }
+
+  if (peer->su_remote)
+    {
+      XFREE (MTYPE_TMP, peer->su_remote);
+      peer->su_remote = NULL;
+    }
+
+  peer->su_local = sockunion_getsockname (peer->fd);
+  peer->su_remote = sockunion_getpeername (peer->fd);
+
+  bgp_nexthop_set (peer->su_local, peer->su_remote, &peer->nexthop, peer);
+}
+
+/* IPv6 supported version of BGP server socket setup.  */
+#if defined (HAVE_IPV6) && ! defined (NRL)
+int
+bgp_socket (struct bgp *bgp, unsigned short port)
+{
+  int ret;
+  struct addrinfo req;
+  struct addrinfo *ainfo;
+  struct addrinfo *ainfo_save;
+  int sock = 0;
+  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;
+  sprintf (port_str, "%d", port);
+  port_str[sizeof (port_str) - 1] = '\0';
+
+  ret = getaddrinfo (NULL, port_str, &req, &ainfo);
+  if (ret != 0)
+    {
+      zlog_err ("getaddrinfo: %s", gai_strerror (ret));
+      return -1;
+    }
+
+  ainfo_save = ainfo;
+
+  do
+    {
+      if (ainfo->ai_family != AF_INET && ainfo->ai_family != AF_INET6)
+	continue;
+     
+      sock = socket (ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol);
+      if (sock < 0)
+	{
+	  zlog_err ("socket: %s", strerror (errno));
+	  continue;
+	}
+
+      sockopt_reuseaddr (sock);
+      sockopt_reuseport (sock);
+
+      ret = bind (sock, ainfo->ai_addr, ainfo->ai_addrlen);
+      if (ret < 0)
+	{
+	  zlog_err ("bind: %s", strerror (errno));
+	  close (sock);
+	  continue;
+	}
+      ret = listen (sock, 3);
+      if (ret < 0) 
+	{
+	  zlog_err ("listen: %s", strerror (errno));
+	  close (sock);
+	  continue;
+	}
+
+      thread_add_read (master, bgp_accept, bgp, sock);
+    }
+  while ((ainfo = ainfo->ai_next) != NULL);
+
+  freeaddrinfo (ainfo_save);
+
+  return sock;
+}
+#else
+/* Traditional IPv4 only version.  */
+int
+bgp_socket (struct bgp *bgp, unsigned short port)
+{
+  int sock;
+  int socklen;
+  struct sockaddr_in sin;
+  int ret;
+
+  sock = socket (AF_INET, SOCK_STREAM, 0);
+  if (sock < 0)
+    {
+      zlog_err ("socket: %s", strerror (errno));
+      return sock;
+    }
+
+  sockopt_reuseaddr (sock);
+  sockopt_reuseport (sock);
+
+  memset (&sin, 0, sizeof (struct sockaddr_in));
+
+  sin.sin_family = AF_INET;
+  sin.sin_port = htons (port);
+  socklen = sizeof (struct sockaddr_in);
+#ifdef HAVE_SIN_LEN
+  sin.sin_len = socklen;
+#endif /* HAVE_SIN_LEN */
+
+  ret = bind (sock, (struct sockaddr *) &sin, socklen);
+  if (ret < 0)
+    {
+      zlog_err ("bind: %s", strerror (errno));
+      close (sock);
+      return ret;
+    }
+  ret = listen (sock, 3);
+  if (ret < 0) 
+    {
+      zlog_err ("listen: %s", strerror (errno));
+      close (sock);
+      return ret;
+    }
+
+  thread_add_read (bm->master, bgp_accept, bgp, sock);
+
+  return sock;
+}
+#endif /* HAVE_IPV6 && !NRL */
diff --git a/bgpd/bgp_network.h b/bgpd/bgp_network.h
new file mode 100644
index 0000000..b994987
--- /dev/null
+++ b/bgpd/bgp_network.h
@@ -0,0 +1,23 @@
+/* BGP network related header
+   Copyright (C) 1999 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+int bgp_socket (struct bgp *, unsigned short);
+int bgp_connect (struct peer *);
+void bgp_getsockname (struct peer *);
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
new file mode 100644
index 0000000..24a113d
--- /dev/null
+++ b/bgpd/bgp_nexthop.c
@@ -0,0 +1,1405 @@
+/* BGP nexthop scan
+   Copyright (C) 2000 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "command.h"
+#include "thread.h"
+#include "prefix.h"
+#include "zclient.h"
+#include "stream.h"
+#include "network.h"
+#include "log.h"
+#include "memory.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_table.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_nexthop.h"
+#include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_damp.h"
+#include "zebra/rib.h"
+#include "zebra/zserv.h"	/* For ZEBRA_SERV_PATH. */
+
+struct bgp_nexthop_cache *zlookup_query (struct in_addr);
+#ifdef HAVE_IPV6
+struct bgp_nexthop_cache *zlookup_query_ipv6 (struct in6_addr *);
+#endif /* HAVE_IPV6 */
+
+/* Only one BGP scan thread are activated at the same time. */
+struct thread *bgp_scan_thread = NULL;
+
+/* BGP import thread */
+struct thread *bgp_import_thread = NULL;
+
+/* BGP scan interval. */
+int bgp_scan_interval;
+
+/* BGP import interval. */
+int bgp_import_interval;
+
+/* Route table for next-hop lookup cache. */
+struct bgp_table *bgp_nexthop_cache_ipv4;
+struct bgp_table *cache1;
+struct bgp_table *cache2;
+
+/* Route table for next-hop lookup cache. */
+struct bgp_table *bgp_nexthop_cache_ipv6;
+struct bgp_table *cache6_1;
+struct bgp_table *cache6_2;
+
+/* Route table for connected route. */
+struct bgp_table *bgp_connected_ipv4;
+
+/* Route table for connected route. */
+struct bgp_table *bgp_connected_ipv6;
+
+/* BGP nexthop lookup query client. */
+static struct zclient *zlookup = NULL;
+
+/* BGP process function. */
+int bgp_process (struct bgp *, struct bgp_node *, afi_t, safi_t);
+
+/* Add nexthop to the end of the list.  */
+void
+bnc_nexthop_add (struct bgp_nexthop_cache *bnc, struct nexthop *nexthop)
+{
+  struct nexthop *last;
+
+  for (last = bnc->nexthop; last && last->next; last = last->next)
+    ;
+  if (last)
+    last->next = nexthop;
+  else
+    bnc->nexthop = nexthop;
+  nexthop->prev = last;
+}
+
+void
+bnc_nexthop_free (struct bgp_nexthop_cache *bnc)
+{
+  struct nexthop *nexthop;
+  struct nexthop *next = NULL;
+
+  for (nexthop = bnc->nexthop; nexthop; nexthop = next)
+    {
+      next = nexthop->next;
+      XFREE (MTYPE_NEXTHOP, nexthop);
+    }
+}
+
+struct bgp_nexthop_cache *
+bnc_new ()
+{
+  struct bgp_nexthop_cache *new;
+
+  new = XMALLOC (MTYPE_BGP_NEXTHOP_CACHE, sizeof (struct bgp_nexthop_cache));
+  memset (new, 0, sizeof (struct bgp_nexthop_cache));
+  return new;
+}
+
+void
+bnc_free (struct bgp_nexthop_cache *bnc)
+{
+  bnc_nexthop_free (bnc);
+  XFREE (MTYPE_BGP_NEXTHOP_CACHE, bnc);
+}
+
+int
+bgp_nexthop_same (struct nexthop *next1, struct nexthop *next2)
+{
+  if (next1->type != next2->type)
+    return 0;
+
+  switch (next1->type)
+    {
+    case ZEBRA_NEXTHOP_IPV4:
+      if (! IPV4_ADDR_SAME (&next1->gate.ipv4, &next2->gate.ipv4))
+	return 0;
+      break;
+    case ZEBRA_NEXTHOP_IFINDEX:
+    case ZEBRA_NEXTHOP_IFNAME:
+      if (next1->ifindex != next2->ifindex)
+	return 0;
+      break;
+#ifdef HAVE_IPV6
+    case ZEBRA_NEXTHOP_IPV6:
+      if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6))
+	return 0;
+      break;
+    case ZEBRA_NEXTHOP_IPV6_IFINDEX:
+    case ZEBRA_NEXTHOP_IPV6_IFNAME:
+      if (! IPV6_ADDR_SAME (&next1->gate.ipv6, &next2->gate.ipv6))
+	return 0;
+      if (next1->ifindex != next2->ifindex)
+	return 0;
+      break;
+#endif /* HAVE_IPV6 */
+    }
+  return 1;
+}
+
+int
+bgp_nexthop_cache_changed (struct bgp_nexthop_cache *bnc1,
+			   struct bgp_nexthop_cache *bnc2)
+{
+  int i;
+  struct nexthop *next1, *next2;
+
+  if (bnc1->nexthop_num != bnc2->nexthop_num)
+    return 1;
+
+  next1 = bnc1->nexthop;
+  next2 = bnc2->nexthop;
+
+  for (i = 0; i < bnc1->nexthop_num; i++)
+    {
+      if (! bgp_nexthop_same (next1, next2))
+	return 1;
+
+      next1 = next1->next;
+      next2 = next2->next;
+    }
+  return 0;
+}
+
+/* If nexthop exists on connected network return 1. */
+int
+bgp_nexthop_check_ebgp (afi_t afi, struct attr *attr)
+{
+  struct bgp_node *rn;
+
+  /* If zebra is not enabled return */
+  if (zlookup->sock < 0)
+    return 1;
+
+  /* Lookup the address is onlink or not. */
+  if (afi == AFI_IP)
+    {
+      rn = bgp_node_match_ipv4 (bgp_connected_ipv4, &attr->nexthop);
+      if (rn)
+	{
+	  bgp_unlock_node (rn);
+	  return 1;
+	}
+    }
+#ifdef HAVE_IPV6
+  else if (afi == AFI_IP6)
+    {
+      if (attr->mp_nexthop_len == 32)
+	return 1;
+      else if (attr->mp_nexthop_len == 16)
+	{
+	  if (IN6_IS_ADDR_LINKLOCAL (&attr->mp_nexthop_global))
+	    return 1;
+
+	  rn = bgp_node_match_ipv6 (bgp_connected_ipv6,
+				      &attr->mp_nexthop_global);
+	  if (rn)
+	    {
+	      bgp_unlock_node (rn);
+	      return 1;
+	    }
+	}
+    }
+#endif /* HAVE_IPV6 */
+  return 0;
+}
+
+#ifdef HAVE_IPV6
+/* Check specified next-hop is reachable or not. */
+int
+bgp_nexthop_lookup_ipv6 (struct peer *peer, struct bgp_info *ri, int *changed,
+			 int *metricchanged)
+{
+  struct bgp_node *rn;
+  struct prefix p;
+  struct bgp_nexthop_cache *bnc;
+  struct attr *attr;
+
+  /* If lookup is not enabled, return valid. */
+  if (zlookup->sock < 0)
+    {
+      ri->igpmetric = 0;
+      return 1;
+    }
+
+  /* Only check IPv6 global address only nexthop. */
+  attr = ri->attr;
+
+  if (attr->mp_nexthop_len != 16 
+      || IN6_IS_ADDR_LINKLOCAL (&attr->mp_nexthop_global))
+    return 1;
+
+  memset (&p, 0, sizeof (struct prefix));
+  p.family = AF_INET6;
+  p.prefixlen = IPV6_MAX_BITLEN;
+  p.u.prefix6 = attr->mp_nexthop_global;
+
+  /* IBGP or ebgp-multihop */
+  rn = bgp_node_get (bgp_nexthop_cache_ipv6, &p);
+
+  if (rn->info)
+    {
+      bnc = rn->info;
+      bgp_unlock_node (rn);
+    }
+  else
+    {
+      bnc = zlookup_query_ipv6 (&attr->mp_nexthop_global);
+      if (bnc)
+	{
+	  struct bgp_table *old;
+	  struct bgp_node *oldrn;
+	  struct bgp_nexthop_cache *oldbnc;
+
+	  if (changed)
+	    {
+	      if (bgp_nexthop_cache_ipv6 == cache6_1)
+		old = cache6_2;
+	      else
+		old = cache6_1;
+
+	      oldrn = bgp_node_lookup (old, &p);
+	      if (oldrn)
+		{
+		  oldbnc = oldrn->info;
+
+		  bnc->changed = bgp_nexthop_cache_changed (bnc, oldbnc);
+
+		  if (bnc->metric != oldbnc->metric)
+		    bnc->metricchanged = 1;
+		}
+	    }
+	}
+      else
+	{
+	  bnc = bnc_new ();
+	  bnc->valid = 0;
+	}
+      rn->info = bnc;
+    }
+
+  if (changed)
+    *changed = bnc->changed;
+
+  if (metricchanged)
+    *metricchanged = bnc->metricchanged;
+
+  if (bnc->valid)
+    ri->igpmetric = bnc->metric;
+  else
+    ri->igpmetric = 0;
+
+  return bnc->valid;
+}
+#endif /* HAVE_IPV6 */
+
+/* Check specified next-hop is reachable or not. */
+int
+bgp_nexthop_lookup (afi_t afi, struct peer *peer, struct bgp_info *ri,
+		    int *changed, int *metricchanged)
+{
+  struct bgp_node *rn;
+  struct prefix p;
+  struct bgp_nexthop_cache *bnc;
+  struct in_addr addr;
+
+  /* If lookup is not enabled, return valid. */
+  if (zlookup->sock < 0)
+    {
+      ri->igpmetric = 0;
+      return 1;
+    }
+
+#ifdef HAVE_IPV6
+  if (afi == AFI_IP6)
+    return bgp_nexthop_lookup_ipv6 (peer, ri, changed, metricchanged);
+#endif /* HAVE_IPV6 */
+
+  addr = ri->attr->nexthop;
+
+  memset (&p, 0, sizeof (struct prefix));
+  p.family = AF_INET;
+  p.prefixlen = IPV4_MAX_BITLEN;
+  p.u.prefix4 = addr;
+
+  /* IBGP or ebgp-multihop */
+  rn = bgp_node_get (bgp_nexthop_cache_ipv4, &p);
+
+  if (rn->info)
+    {
+      bnc = rn->info;
+      bgp_unlock_node (rn);
+    }
+  else
+    {
+      bnc = zlookup_query (addr);
+      if (bnc)
+	{
+	  struct bgp_table *old;
+	  struct bgp_node *oldrn;
+	  struct bgp_nexthop_cache *oldbnc;
+
+	  if (changed)
+	    {
+	      if (bgp_nexthop_cache_ipv4 == cache1)
+		old = cache2;
+	      else
+		old = cache1;
+
+	      oldrn = bgp_node_lookup (old, &p);
+	      if (oldrn)
+		{
+		  oldbnc = oldrn->info;
+
+		  bnc->changed = bgp_nexthop_cache_changed (bnc, oldbnc);
+
+		  if (bnc->metric != oldbnc->metric)
+		    bnc->metricchanged = 1;
+		}
+	    }
+	}
+      else
+	{
+	  bnc = bnc_new ();
+	  bnc->valid = 0;
+	}
+      rn->info = bnc;
+    }
+
+  if (changed)
+    *changed = bnc->changed;
+
+  if (metricchanged)
+    *metricchanged = bnc->metricchanged;
+
+  if (bnc->valid)
+    ri->igpmetric = bnc->metric;
+  else
+    ri->igpmetric = 0;
+
+  return bnc->valid;
+}
+
+/* Reset and free all BGP nexthop cache. */
+void
+bgp_nexthop_cache_reset (struct bgp_table *table)
+{
+  struct bgp_node *rn;
+  struct bgp_nexthop_cache *bnc;
+
+  for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
+    if ((bnc = rn->info) != NULL)
+      {
+	bnc_free (bnc);
+	rn->info = NULL;
+	bgp_unlock_node (rn);
+      }
+}
+
+void
+bgp_scan_ipv4 ()
+{
+  struct bgp_node *rn;
+  struct bgp *bgp;
+  struct bgp_info *bi;
+  struct bgp_info *next;
+  struct peer *peer;
+  struct listnode *nn;
+  int valid;
+  int current;
+  int changed;
+  int metricchanged;
+
+  /* Change cache. */
+  if (bgp_nexthop_cache_ipv4 == cache1)
+    bgp_nexthop_cache_ipv4 = cache2;
+  else
+    bgp_nexthop_cache_ipv4 = cache1;
+
+  /* Get default bgp. */
+  bgp = bgp_get_default ();
+  if (bgp == NULL)
+    return;
+
+  /* Maximum prefix check */
+  LIST_LOOP (bgp->peer, peer, nn)
+    {
+      if (peer->status != Established)
+	continue;
+
+      if (peer->afc[AFI_IP][SAFI_UNICAST])
+	bgp_maximum_prefix_overflow (peer, AFI_IP, SAFI_UNICAST);
+      if (peer->afc[AFI_IP][SAFI_MULTICAST])
+	bgp_maximum_prefix_overflow (peer, AFI_IP, SAFI_MULTICAST);
+      if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
+	bgp_maximum_prefix_overflow (peer, AFI_IP, SAFI_MPLS_VPN);
+    }
+
+  for (rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_UNICAST]); rn;
+       rn = bgp_route_next (rn))
+    {
+      for (bi = rn->info; bi; bi = next)
+	{
+	  next = bi->next;
+
+	  if (bi->type == ZEBRA_ROUTE_BGP && bi->sub_type == BGP_ROUTE_NORMAL)
+	    {
+	      changed = 0;
+	      metricchanged = 0;
+
+	      if (peer_sort (bi->peer) == BGP_PEER_EBGP && bi->peer->ttl == 1)
+		valid = bgp_nexthop_check_ebgp (AFI_IP, bi->attr);
+	      else
+		valid = bgp_nexthop_lookup (AFI_IP, bi->peer, bi,
+					    &changed, &metricchanged);
+
+	      current = CHECK_FLAG (bi->flags, BGP_INFO_VALID) ? 1 : 0;
+
+	      if (changed)
+		SET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED);
+	      else
+		UNSET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED);
+
+	      if (valid != current)
+		{
+		  if (CHECK_FLAG (bi->flags, BGP_INFO_VALID))
+		    {
+		      bgp_aggregate_decrement (bgp, &rn->p, bi,
+					       AFI_IP, SAFI_UNICAST);
+		      UNSET_FLAG (bi->flags, BGP_INFO_VALID);
+		    }
+		  else
+		    {
+		      SET_FLAG (bi->flags, BGP_INFO_VALID);
+		      bgp_aggregate_increment (bgp, &rn->p, bi,
+					       AFI_IP, SAFI_UNICAST);
+		    }
+		}
+
+              if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
+		  BGP_CONFIG_DAMPENING)
+                  &&  bi->damp_info )
+                if (bgp_damp_scan (bi, AFI_IP, SAFI_UNICAST))
+		  bgp_aggregate_increment (bgp, &rn->p, bi,
+					   AFI_IP, SAFI_UNICAST);
+	    }
+	}
+      bgp_process (bgp, rn, AFI_IP, SAFI_UNICAST);
+    }
+
+  /* Flash old cache. */
+  if (bgp_nexthop_cache_ipv4 == cache1)
+    bgp_nexthop_cache_reset (cache2);
+  else
+    bgp_nexthop_cache_reset (cache1);
+}
+
+#ifdef HAVE_IPV6
+void
+bgp_scan_ipv6 ()
+{
+  struct bgp_node *rn;
+  struct bgp *bgp;
+  struct bgp_info *bi;
+  struct bgp_info *next;
+  struct peer *peer;
+  struct listnode *nn;
+  int valid;
+  int current;
+  int changed;
+  int metricchanged;
+
+  /* Change cache. */
+  if (bgp_nexthop_cache_ipv6 == cache6_1)
+    bgp_nexthop_cache_ipv6 = cache6_2;
+  else
+    bgp_nexthop_cache_ipv6 = cache6_1;
+
+  /* Get default bgp. */
+  bgp = bgp_get_default ();
+  if (bgp == NULL)
+    return;
+
+  /* Maximum prefix check */
+  LIST_LOOP (bgp->peer, peer, nn)
+    {
+      if (peer->status != Established)
+	continue;
+
+      if (peer->afc[AFI_IP6][SAFI_UNICAST])
+	bgp_maximum_prefix_overflow (peer, AFI_IP6, SAFI_UNICAST);
+      if (peer->afc[AFI_IP6][SAFI_MULTICAST])
+	bgp_maximum_prefix_overflow (peer, AFI_IP6, SAFI_MULTICAST);
+    }
+
+  for (rn = bgp_table_top (bgp->rib[AFI_IP6][SAFI_UNICAST]); rn;
+       rn = bgp_route_next (rn))
+    {
+      for (bi = rn->info; bi; bi = next)
+	{
+	  next = bi->next;
+
+	  if (bi->type == ZEBRA_ROUTE_BGP && bi->sub_type == BGP_ROUTE_NORMAL)
+	    {
+	      changed = 0;
+	      metricchanged = 0;
+
+	      if (peer_sort (bi->peer) == BGP_PEER_EBGP && bi->peer->ttl == 1)
+		valid = 1;
+	      else
+		valid = bgp_nexthop_lookup_ipv6 (bi->peer, bi,
+						 &changed, &metricchanged);
+
+	      current = CHECK_FLAG (bi->flags, BGP_INFO_VALID) ? 1 : 0;
+
+	      if (changed)
+		SET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED);
+	      else
+		UNSET_FLAG (bi->flags, BGP_INFO_IGP_CHANGED);
+
+	      if (valid != current)
+		{
+		  if (CHECK_FLAG (bi->flags, BGP_INFO_VALID))
+		    {
+		      bgp_aggregate_decrement (bgp, &rn->p, bi,
+					       AFI_IP6, SAFI_UNICAST);
+		      UNSET_FLAG (bi->flags, BGP_INFO_VALID);
+		    }
+		  else
+		    {
+		      SET_FLAG (bi->flags, BGP_INFO_VALID);
+		      bgp_aggregate_increment (bgp, &rn->p, bi,
+					       AFI_IP6, SAFI_UNICAST);
+		    }
+		}
+
+              if (CHECK_FLAG (bgp->af_flags[AFI_IP6][SAFI_UNICAST],
+		  BGP_CONFIG_DAMPENING)
+                  &&  bi->damp_info )
+                if (bgp_damp_scan (bi, AFI_IP6, SAFI_UNICAST))
+		  bgp_aggregate_increment (bgp, &rn->p, bi,
+					   AFI_IP6, SAFI_UNICAST);
+	    }
+	}
+      bgp_process (bgp, rn, AFI_IP6, SAFI_UNICAST);
+    }
+
+  /* Flash old cache. */
+  if (bgp_nexthop_cache_ipv6 == cache6_1)
+    bgp_nexthop_cache_reset (cache6_2);
+  else
+    bgp_nexthop_cache_reset (cache6_1);
+}
+#endif /* HAVE_IPV6 */
+
+/* BGP scan thread.  This thread check nexthop reachability. */
+int
+bgp_scan (struct thread *t)
+{
+  bgp_scan_thread =
+    thread_add_timer (master, bgp_scan, NULL, bgp_scan_interval);
+
+  if (BGP_DEBUG (normal, NORMAL))
+    zlog_info ("Performing BGP general scanning");
+
+  bgp_scan_ipv4 ();
+
+#ifdef HAVE_IPV6
+  bgp_scan_ipv6 ();
+#endif /* HAVE_IPV6 */
+
+  return 0;
+}
+
+struct bgp_connected
+{
+  unsigned int refcnt;
+};
+
+void
+bgp_connected_add (struct connected *ifc)
+{
+  struct prefix p;
+  struct prefix *addr;
+  struct prefix *dest;
+  struct interface *ifp;
+  struct bgp_node *rn;
+  struct bgp_connected *bc;
+
+  ifp = ifc->ifp;
+
+  if (! ifp)
+    return;
+
+  if (if_is_loopback (ifp))
+    return;
+
+  addr = ifc->address;
+  dest = ifc->destination;
+
+  if (addr->family == AF_INET)
+    {
+      memset (&p, 0, sizeof (struct prefix));
+      p.family = AF_INET;
+      p.prefixlen = addr->prefixlen;
+
+      if (if_is_pointopoint (ifp))
+	p.u.prefix4 = dest->u.prefix4;
+      else
+	p.u.prefix4 = addr->u.prefix4;
+
+      apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
+
+      if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
+	return;
+
+      rn = bgp_node_get (bgp_connected_ipv4, (struct prefix *) &p);
+      if (rn->info)
+	{
+	  bc = rn->info;
+	  bc->refcnt++;
+	}
+      else
+	{
+	  bc = XMALLOC (0, sizeof (struct bgp_connected));
+	  memset (bc, 0, sizeof (struct bgp_connected));
+	  bc->refcnt = 1;
+	  rn->info = bc;
+	}
+    }
+#ifdef HAVE_IPV6
+  if (addr->family == AF_INET6)
+    {
+      memset (&p, 0, sizeof (struct prefix));
+      p.family = AF_INET6;
+      p.prefixlen = addr->prefixlen;
+
+      if (if_is_pointopoint (ifp))
+	p.u.prefix6 = dest->u.prefix6;
+      else
+	p.u.prefix6 = addr->u.prefix6;
+
+      apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
+
+      if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
+	return;
+
+      if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
+	return;
+
+      rn = bgp_node_get (bgp_connected_ipv6, (struct prefix *) &p);
+      if (rn->info)
+	{
+	  bc = rn->info;
+	  bc->refcnt++;
+	}
+      else
+	{
+	  bc = XMALLOC (0, sizeof (struct bgp_connected));
+	  memset (bc, 0, sizeof (struct bgp_connected));
+	  bc->refcnt = 1;
+	  rn->info = bc;
+	}
+    }
+#endif /* HAVE_IPV6 */
+}
+
+void
+bgp_connected_delete (struct connected *ifc)
+{
+  struct prefix p;
+  struct prefix *addr;
+  struct prefix *dest;
+  struct interface *ifp;
+  struct bgp_node *rn;
+  struct bgp_connected *bc;
+
+  ifp = ifc->ifp;
+
+  if (if_is_loopback (ifp))
+    return;
+
+  addr = ifc->address;
+  dest = ifc->destination;
+
+  if (addr->family == AF_INET)
+    {
+      memset (&p, 0, sizeof (struct prefix));
+      p.family = AF_INET;
+      p.prefixlen = addr->prefixlen;
+
+      if (if_is_pointopoint (ifp))
+	p.u.prefix4 = dest->u.prefix4;
+      else
+	p.u.prefix4 = addr->u.prefix4;
+
+      apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
+
+      if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
+	return;
+
+      rn = bgp_node_lookup (bgp_connected_ipv4, &p);
+      if (! rn)
+	return;
+
+      bc = rn->info;
+      bc->refcnt--;
+      if (bc->refcnt == 0)
+	{
+	  XFREE (0, bc);
+	  rn->info = NULL;
+	}
+      bgp_unlock_node (rn);
+      bgp_unlock_node (rn);
+    }
+#ifdef HAVE_IPV6
+  else if (addr->family == AF_INET6)
+    {
+      memset (&p, 0, sizeof (struct prefix));
+      p.family = AF_INET6;
+      p.prefixlen = addr->prefixlen;
+
+      if (if_is_pointopoint (ifp))
+	p.u.prefix6 = dest->u.prefix6;
+      else
+	p.u.prefix6 = addr->u.prefix6;
+
+      apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
+
+      if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
+	return;
+
+      if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
+	return;
+
+      rn = bgp_node_lookup (bgp_connected_ipv6, (struct prefix *) &p);
+      if (! rn)
+	return;
+
+      bc = rn->info;
+      bc->refcnt--;
+      if (bc->refcnt == 0)
+	{
+	  XFREE (0, bc);
+	  rn->info = NULL;
+	}
+      bgp_unlock_node (rn);
+      bgp_unlock_node (rn);
+    }
+#endif /* HAVE_IPV6 */
+}
+
+int
+bgp_nexthop_self (afi_t afi, struct attr *attr)
+{
+  listnode node;
+  listnode node2;
+  struct interface *ifp;
+  struct connected *ifc;
+  struct prefix *p;
+
+  for (node = listhead (iflist); node; nextnode (node))
+    {
+      ifp = getdata (node);
+
+      for (node2 = listhead (ifp->connected); node2; nextnode (node2))
+	{
+	  ifc = getdata (node2);
+	  p = ifc->address;
+
+	  if (p && p->family == AF_INET 
+	      && IPV4_ADDR_SAME (&p->u.prefix4, &attr->nexthop))
+	    return 1;
+	}
+    }
+  return 0;
+}
+
+struct bgp_nexthop_cache *
+zlookup_read ()
+{
+  struct stream *s;
+  u_int16_t length;
+  u_char command;
+  int nbytes;
+  struct in_addr raddr;
+  u_int32_t metric;
+  int i;
+  u_char nexthop_num;
+  struct nexthop *nexthop;
+  struct bgp_nexthop_cache *bnc;
+
+  s = zlookup->ibuf;
+  stream_reset (s);
+
+  nbytes = stream_read (s, zlookup->sock, 2);
+  length = stream_getw (s);
+
+  nbytes = stream_read (s, zlookup->sock, length - 2);
+  command = stream_getc (s);
+  raddr.s_addr = stream_get_ipv4 (s);
+  metric = stream_getl (s);
+  nexthop_num = stream_getc (s);
+
+  if (nexthop_num)
+    {
+      bnc = bnc_new ();
+      bnc->valid = 1;
+      bnc->metric = metric;
+      bnc->nexthop_num = nexthop_num;
+
+      for (i = 0; i < nexthop_num; i++)
+	{
+	  nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
+	  memset (nexthop, 0, sizeof (struct nexthop));
+	  nexthop->type = stream_getc (s);
+	  switch (nexthop->type)
+	    {
+	    case ZEBRA_NEXTHOP_IPV4:
+	      nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s);
+	      break;
+	    case ZEBRA_NEXTHOP_IFINDEX:
+	    case ZEBRA_NEXTHOP_IFNAME:
+	      nexthop->ifindex = stream_getl (s);
+	      break;
+	    }
+	  bnc_nexthop_add (bnc, nexthop);
+	}
+    }
+  else
+    return NULL;
+
+  return bnc;
+}
+
+struct bgp_nexthop_cache *
+zlookup_query (struct in_addr addr)
+{
+  int ret;
+  struct stream *s;
+
+  /* Check socket. */
+  if (zlookup->sock < 0)
+    return NULL;
+
+  s = zlookup->obuf;
+  stream_reset (s);
+  stream_putw (s, 7);
+  stream_putc (s, ZEBRA_IPV4_NEXTHOP_LOOKUP);
+  stream_put_in_addr (s, &addr);
+
+  ret = writen (zlookup->sock, s->data, 7);
+  if (ret < 0)
+    {
+      zlog_err ("can't write to zlookup->sock");
+      close (zlookup->sock);
+      zlookup->sock = -1;
+      return NULL;
+    }
+  if (ret == 0)
+    {
+      zlog_err ("zlookup->sock connection closed");
+      close (zlookup->sock);
+      zlookup->sock = -1;
+      return NULL;
+    }
+
+  return zlookup_read ();
+}
+
+#ifdef HAVE_IPV6
+struct bgp_nexthop_cache *
+zlookup_read_ipv6 ()
+{
+  struct stream *s;
+  u_int16_t length;
+  u_char command;
+  int nbytes;
+  struct in6_addr raddr;
+  u_int32_t metric;
+  int i;
+  u_char nexthop_num;
+  struct nexthop *nexthop;
+  struct bgp_nexthop_cache *bnc;
+
+  s = zlookup->ibuf;
+  stream_reset (s);
+
+  nbytes = stream_read (s, zlookup->sock, 2);
+  length = stream_getw (s);
+
+  nbytes = stream_read (s, zlookup->sock, length - 2);
+  command = stream_getc (s);
+
+  stream_get (&raddr, s, 16);
+
+  metric = stream_getl (s);
+  nexthop_num = stream_getc (s);
+
+  if (nexthop_num)
+    {
+      bnc = bnc_new ();
+      bnc->valid = 1;
+      bnc->metric = metric;
+      bnc->nexthop_num = nexthop_num;
+
+      for (i = 0; i < nexthop_num; i++)
+	{
+	  nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop));
+	  memset (nexthop, 0, sizeof (struct nexthop));
+	  nexthop->type = stream_getc (s);
+	  switch (nexthop->type)
+	    {
+	    case ZEBRA_NEXTHOP_IPV6:
+	      stream_get (&nexthop->gate.ipv6, s, 16);
+	      break;
+	    case ZEBRA_NEXTHOP_IPV6_IFINDEX:
+	    case ZEBRA_NEXTHOP_IPV6_IFNAME:
+	      stream_get (&nexthop->gate.ipv6, s, 16);
+	      nexthop->ifindex = stream_getl (s);
+	      break;
+	    case ZEBRA_NEXTHOP_IFINDEX:
+	    case ZEBRA_NEXTHOP_IFNAME:
+	      nexthop->ifindex = stream_getl (s);
+	      break;
+	    }
+	  bnc_nexthop_add (bnc, nexthop);
+	}
+    }
+  else
+    return NULL;
+
+  return bnc;
+}
+
+struct bgp_nexthop_cache *
+zlookup_query_ipv6 (struct in6_addr *addr)
+{
+  int ret;
+  struct stream *s;
+
+  /* Check socket. */
+  if (zlookup->sock < 0)
+    return NULL;
+
+  s = zlookup->obuf;
+  stream_reset (s);
+  stream_putw (s, 19);
+  stream_putc (s, ZEBRA_IPV6_NEXTHOP_LOOKUP);
+  stream_put (s, addr, 16);
+
+  ret = writen (zlookup->sock, s->data, 19);
+  if (ret < 0)
+    {
+      zlog_err ("can't write to zlookup->sock");
+      close (zlookup->sock);
+      zlookup->sock = -1;
+      return NULL;
+    }
+  if (ret == 0)
+    {
+      zlog_err ("zlookup->sock connection closed");
+      close (zlookup->sock);
+      zlookup->sock = -1;
+      return NULL;
+    }
+
+  return zlookup_read_ipv6 ();
+}
+#endif /* HAVE_IPV6 */
+
+int
+bgp_import_check (struct prefix *p, u_int32_t *igpmetric, struct in_addr *igpnexthop)
+{
+  struct stream *s;
+  int ret;
+  u_int16_t length;
+  u_char command;
+  int nbytes;
+  struct in_addr addr;
+  struct in_addr nexthop;
+  u_int32_t metric = 0;
+  u_char nexthop_num;
+  u_char nexthop_type;
+
+  /* If lookup connection is not available return valid. */
+  if (zlookup->sock < 0)
+    {
+      if (igpmetric)
+	*igpmetric = 0;
+      return 1;
+    }
+
+  /* Send query to the lookup connection */
+  s = zlookup->obuf;
+  stream_reset (s);
+  stream_putw (s, 8);
+  stream_putc (s, ZEBRA_IPV4_IMPORT_LOOKUP);
+  stream_putc (s, p->prefixlen);
+  stream_put_in_addr (s, &p->u.prefix4);
+
+  /* Write the packet. */
+  ret = writen (zlookup->sock, s->data, 8);
+
+  if (ret < 0)
+    {
+      zlog_err ("can't write to zlookup->sock");
+      close (zlookup->sock);
+      zlookup->sock = -1;
+      return 1;
+    }
+  if (ret == 0)
+    {
+      zlog_err ("zlookup->sock connection closed");
+      close (zlookup->sock);
+      zlookup->sock = -1;
+      return 1;
+    }
+
+  /* Get result. */
+  stream_reset (s);
+
+  /* Fetch length. */
+  nbytes = stream_read (s, zlookup->sock, 2);
+  length = stream_getw (s);
+
+  /* Fetch whole data. */
+  nbytes = stream_read (s, zlookup->sock, length - 2);
+  command = stream_getc (s);
+  addr.s_addr = stream_get_ipv4 (s);
+  metric = stream_getl (s);
+  nexthop_num = stream_getc (s);
+
+  /* Set IGP metric value. */
+  if (igpmetric)
+    *igpmetric = metric;
+
+  /* If there is nexthop then this is active route. */
+  if (nexthop_num)
+    {
+      nexthop.s_addr = 0;
+      nexthop_type = stream_getc (s);
+      if (nexthop_type == ZEBRA_NEXTHOP_IPV4)
+	{
+	  nexthop.s_addr = stream_get_ipv4 (s);
+	  if (igpnexthop)
+	    *igpnexthop = nexthop;
+	}
+      else
+	*igpnexthop = nexthop;
+
+      return 1;
+    }
+  else
+    return 0;
+}
+
+/* Scan all configured BGP route then check the route exists in IGP or
+   not. */
+int
+bgp_import (struct thread *t)
+{
+  struct bgp *bgp;
+  struct bgp_node *rn;
+  struct bgp_static *bgp_static;
+  int valid;
+  u_int32_t metric;
+  struct in_addr nexthop;
+  afi_t afi;
+  safi_t safi;
+
+  bgp_import_thread = 
+    thread_add_timer (master, bgp_import, NULL, bgp_import_interval);
+
+  bgp = bgp_get_default ();
+  if (! bgp)
+    return 0;
+
+  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+    for (safi = SAFI_UNICAST; safi < SAFI_MPLS_VPN; safi++)
+      for (rn = bgp_table_top (bgp->route[afi][safi]); rn;
+	   rn = bgp_route_next (rn))
+	if ((bgp_static = rn->info) != NULL)
+	  {
+	    if (bgp_static->backdoor)
+	      continue;
+
+	    valid = bgp_static->valid;
+	    metric = bgp_static->igpmetric;
+	    nexthop = bgp_static->igpnexthop;
+
+	    if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK)
+		&& afi == AFI_IP && safi == SAFI_UNICAST)
+	      bgp_static->valid = bgp_import_check (&rn->p, &bgp_static->igpmetric,
+						    &bgp_static->igpnexthop);
+	    else
+	      {
+		bgp_static->valid = 1;
+		bgp_static->igpmetric = 0;
+		bgp_static->igpnexthop.s_addr = 0;
+	      }
+
+	    if (bgp_static->valid != valid)
+	      {
+		if (bgp_static->valid)
+		  bgp_static_update (bgp, &rn->p, bgp_static, afi, safi);
+		else
+		  bgp_static_withdraw (bgp, &rn->p, afi, safi);
+	      }
+	    else if (bgp_static->valid)
+	      {
+		if (bgp_static->igpmetric != metric
+		    || bgp_static->igpnexthop.s_addr != nexthop.s_addr
+		    || bgp_static->rmap.name)
+		  bgp_static_update (bgp, &rn->p, bgp_static, afi, safi);
+	      }
+	  }
+  return 0;
+}
+
+/* Connect to zebra for nexthop lookup. */
+int
+zlookup_connect (struct thread *t)
+{
+  struct zclient *zlookup;
+
+  zlookup = THREAD_ARG (t);
+  zlookup->t_connect = NULL;
+
+  if (zlookup->sock != -1)
+    return 0;
+
+#ifdef HAVE_TCP_ZEBRA
+  zlookup->sock = zclient_socket ();
+#else
+  zlookup->sock = zclient_socket_un (ZEBRA_SERV_PATH);
+#endif /* HAVE_TCP_ZEBRA */
+  if (zlookup->sock < 0)
+    return -1;
+
+  /* Make BGP import there. */
+  bgp_import_thread = 
+    thread_add_timer (master, bgp_import, NULL, 0);
+
+  return 0;
+}
+
+/* Check specified multiaccess next-hop. */
+int
+bgp_multiaccess_check_v4 (struct in_addr nexthop, char *peer)
+{
+  struct bgp_node *rn1;
+  struct bgp_node *rn2;
+  struct prefix p1;
+  struct prefix p2;
+  struct in_addr addr;
+  int ret;
+
+  ret = inet_aton (peer, &addr);
+  if (! ret)
+    return 0;
+
+  memset (&p1, 0, sizeof (struct prefix));
+  p1.family = AF_INET;
+  p1.prefixlen = IPV4_MAX_BITLEN;
+  p1.u.prefix4 = nexthop;
+  memset (&p2, 0, sizeof (struct prefix));
+  p2.family = AF_INET;
+  p2.prefixlen = IPV4_MAX_BITLEN;
+  p2.u.prefix4 = addr;
+
+  /* If bgp scan is not enabled, return invalid. */
+  if (zlookup->sock < 0)
+    return 0;
+
+  rn1 = bgp_node_match (bgp_connected_ipv4, &p1);
+  if (! rn1)
+    return 0;
+  
+  rn2 = bgp_node_match (bgp_connected_ipv4, &p2);
+  if (! rn2)
+    return 0;
+
+  if (rn1 == rn2)
+    return 1;
+
+  return 0;
+}
+
+DEFUN (bgp_scan_time,
+       bgp_scan_time_cmd,
+       "bgp scan-time <5-60>",
+       "BGP specific commands\n"
+       "Configure background scanner interval\n"
+       "Scanner interval (seconds)\n")
+{
+  bgp_scan_interval = atoi (argv[0]);
+
+  if (bgp_scan_thread)
+    {
+      thread_cancel (bgp_scan_thread);
+      bgp_scan_thread = 
+	thread_add_timer (master, bgp_scan, NULL, bgp_scan_interval);
+    }
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_scan_time,
+       no_bgp_scan_time_cmd,
+       "no bgp scan-time",
+       NO_STR
+       "BGP specific commands\n"
+       "Configure background scanner interval\n")
+{
+  bgp_scan_interval = BGP_SCAN_INTERVAL_DEFAULT;
+
+  if (bgp_scan_thread)
+    {
+      thread_cancel (bgp_scan_thread);
+      bgp_scan_thread = 
+	thread_add_timer (master, bgp_scan, NULL, bgp_scan_interval);
+    }
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_bgp_scan_time,
+       no_bgp_scan_time_val_cmd,
+       "no bgp scan-time <5-60>",
+       NO_STR
+       "BGP specific commands\n"
+       "Configure background scanner interval\n"
+       "Scanner interval (seconds)\n")
+
+DEFUN (show_ip_bgp_scan,
+       show_ip_bgp_scan_cmd,
+       "show ip bgp scan",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "BGP scan status\n")
+{
+  struct bgp_node *rn;
+  struct bgp_nexthop_cache *bnc;
+
+  if (bgp_scan_thread)
+    vty_out (vty, "BGP scan is running%s", VTY_NEWLINE);
+  else
+    vty_out (vty, "BGP scan is not running%s", VTY_NEWLINE);
+  vty_out (vty, "BGP scan interval is %d%s", bgp_scan_interval, VTY_NEWLINE);
+
+  vty_out (vty, "Current BGP nexthop cache:%s", VTY_NEWLINE);
+  for (rn = bgp_table_top (bgp_nexthop_cache_ipv4); rn; rn = bgp_route_next (rn))
+    if ((bnc = rn->info) != NULL)
+      {
+	if (bnc->valid)
+	  vty_out (vty, " %s valid [IGP metric %d]%s",
+		   inet_ntoa (rn->p.u.prefix4), bnc->metric, VTY_NEWLINE);
+	else
+	  vty_out (vty, " %s invalid%s",
+		   inet_ntoa (rn->p.u.prefix4), VTY_NEWLINE);
+      }
+
+#ifdef HAVE_IPV6
+  {
+    char buf[BUFSIZ];
+    for (rn = bgp_table_top (bgp_nexthop_cache_ipv6); rn; rn = bgp_route_next (rn))
+      if ((bnc = rn->info) != NULL)
+	{
+	  if (bnc->valid)
+	    vty_out (vty, " %s valid [IGP metric %d]%s",
+		     inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ),
+		     bnc->metric, VTY_NEWLINE);
+	  else
+	    vty_out (vty, " %s invalid%s",
+		     inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ),
+		     VTY_NEWLINE);
+	}
+  }
+#endif /* HAVE_IPV6 */
+
+  vty_out (vty, "BGP connected route:%s", VTY_NEWLINE);
+  for (rn = bgp_table_top (bgp_connected_ipv4); rn; rn = bgp_route_next (rn))
+    if (rn->info != NULL)
+      vty_out (vty, " %s/%d%s", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
+	       VTY_NEWLINE);
+
+#ifdef HAVE_IPV6
+  {
+    char buf[BUFSIZ];
+
+    for (rn = bgp_table_top (bgp_connected_ipv6); rn; rn = bgp_route_next (rn))
+      if (rn->info != NULL)
+	vty_out (vty, " %s/%d%s",
+		 inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, BUFSIZ),
+		 rn->p.prefixlen,
+		 VTY_NEWLINE);
+  }
+#endif /* HAVE_IPV6 */
+
+  return CMD_SUCCESS;
+}
+
+int
+bgp_config_write_scan_time (struct vty *vty)
+{
+  if (bgp_scan_interval != BGP_SCAN_INTERVAL_DEFAULT)
+    vty_out (vty, " bgp scan-time %d%s", bgp_scan_interval, VTY_NEWLINE);
+  return CMD_SUCCESS;
+}
+
+void
+bgp_scan_init ()
+{
+  zlookup = zclient_new ();
+  zlookup->sock = -1;
+  zlookup->ibuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
+  zlookup->obuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
+  zlookup->t_connect = thread_add_event (master, zlookup_connect, zlookup, 0);
+
+  bgp_scan_interval = BGP_SCAN_INTERVAL_DEFAULT;
+  bgp_import_interval = BGP_IMPORT_INTERVAL_DEFAULT;
+
+  cache1 = bgp_table_init ();
+  cache2 = bgp_table_init ();
+  bgp_nexthop_cache_ipv4 = cache1;
+
+  bgp_connected_ipv4 = bgp_table_init ();
+
+#ifdef HAVE_IPV6
+  cache6_1 = bgp_table_init ();
+  cache6_2 = bgp_table_init ();
+  bgp_nexthop_cache_ipv6 = cache6_1;
+  bgp_connected_ipv6 = bgp_table_init ();
+#endif /* HAVE_IPV6 */
+
+  /* Make BGP scan thread. */
+  bgp_scan_thread = thread_add_timer (master, bgp_scan, NULL, bgp_scan_interval);
+
+  install_element (BGP_NODE, &bgp_scan_time_cmd);
+  install_element (BGP_NODE, &no_bgp_scan_time_cmd);
+  install_element (BGP_NODE, &no_bgp_scan_time_val_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_scan_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_scan_cmd);
+}
diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h
new file mode 100644
index 0000000..5f4255d
--- /dev/null
+++ b/bgpd/bgp_nexthop.h
@@ -0,0 +1,52 @@
+/* BGP nexthop scan
+   Copyright (C) 2000 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#define BGP_SCAN_INTERVAL_DEFAULT   60
+#define BGP_IMPORT_INTERVAL_DEFAULT 15
+
+/* BGP nexthop cache value structure. */
+struct bgp_nexthop_cache
+{
+  /* This nexthop exists in IGP. */
+  u_char valid;
+
+  /* Nexthop is changed. */
+  u_char changed;
+
+  /* Nexthop is changed. */
+  u_char metricchanged;
+
+  /* IGP route's metric. */
+  u_int32_t metric;
+
+  /* Nexthop number and nexthop linked list.*/
+  u_char nexthop_num;
+  struct nexthop *nexthop;
+};
+
+void bgp_scan_init ();
+int bgp_nexthop_lookup (afi_t, struct peer *peer, struct bgp_info *,
+			int *, int *);
+void bgp_connected_add (struct connected *c);
+void bgp_connected_delete (struct connected *c);
+int bgp_multiaccess_check_v4 (struct in_addr, char *);
+int bgp_config_write_scan_time (struct vty *);
+int bgp_nexthop_check_ebgp (afi_t, struct attr *);
+int bgp_nexthop_self (afi_t, struct attr *);
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
new file mode 100644
index 0000000..a3e86b0
--- /dev/null
+++ b/bgpd/bgp_open.c
@@ -0,0 +1,793 @@
+/* BGP open message handling
+   Copyright (C) 1998, 1999 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "linklist.h"
+#include "prefix.h"
+#include "stream.h"
+#include "thread.h"
+#include "log.h"
+#include "command.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_fsm.h"
+#include "bgpd/bgp_packet.h"
+#include "bgpd/bgp_open.h"
+
+/* BGP-4 Multiprotocol Extentions lead us to the complex world. We can
+   negotiate remote peer supports extentions or not. But if
+   remote-peer doesn't supports negotiation process itself.  We would
+   like to do manual configuration.
+
+   So there is many configurable point.  First of all we want set each
+   peer whether we send capability negotiation to the peer or not.
+   Next, if we send capability to the peer we want to set my capabilty
+   inforation at each peer. */
+
+void
+bgp_capability_vty_out (struct vty *vty, struct peer *peer)
+{
+  u_char *pnt;
+  u_char *end;
+  struct capability cap;
+
+  pnt = peer->notify.data;
+  end = pnt + peer->notify.length;
+
+  while (pnt < end)
+    {
+      memcpy(&cap, pnt, sizeof(struct capability));
+
+      if (pnt + 2 > end)
+	return;
+      if (pnt + (cap.length + 2) > end)
+	return;
+
+      if (cap.code == CAPABILITY_CODE_MP)
+	{
+	  vty_out (vty, "  Capability error for: Multi protocol ");
+
+	  switch (ntohs (cap.mpc.afi))
+	    {
+	    case AFI_IP:
+	      vty_out (vty, "AFI IPv4, ");
+	      break;
+	    case AFI_IP6:
+	      vty_out (vty, "AFI IPv6, ");
+	      break;
+	    default:
+	      vty_out (vty, "AFI Unknown %d, ", ntohs (cap.mpc.afi));
+	      break;
+	    }
+	  switch (cap.mpc.safi)
+	    {
+	    case SAFI_UNICAST:
+	      vty_out (vty, "SAFI Unicast");
+	      break;
+	    case SAFI_MULTICAST:
+	      vty_out (vty, "SAFI Multicast");
+	      break;
+	    case SAFI_UNICAST_MULTICAST:
+	      vty_out (vty, "SAFI Unicast Multicast");
+	      break;
+	    case BGP_SAFI_VPNV4:
+	      vty_out (vty, "SAFI MPLS-VPN");
+	      break;
+	    default:
+	      vty_out (vty, "SAFI Unknown %d ", cap.mpc.safi);
+	      break;
+	    }
+	  vty_out (vty, "%s", VTY_NEWLINE);
+	}
+      else if (cap.code >= 128)
+	vty_out (vty, "  Capability error: vendor specific capability code %d",
+		 cap.code);
+      else
+	vty_out (vty, "  Capability error: unknown capability code %d", 
+		 cap.code);
+
+      pnt += cap.length + 2;
+    }
+}
+
+/* Set negotiated capability value. */
+int
+bgp_capability_mp (struct peer *peer, struct capability *cap)
+{
+  if (ntohs (cap->mpc.afi) == AFI_IP)
+    {
+      if (cap->mpc.safi == SAFI_UNICAST)
+	{
+	  peer->afc_recv[AFI_IP][SAFI_UNICAST] = 1;
+
+	  if (peer->afc[AFI_IP][SAFI_UNICAST])
+	    peer->afc_nego[AFI_IP][SAFI_UNICAST] = 1;
+	  else
+	    return -1;
+	}
+      else if (cap->mpc.safi == SAFI_MULTICAST) 
+	{
+	  peer->afc_recv[AFI_IP][SAFI_MULTICAST] = 1;
+
+	  if (peer->afc[AFI_IP][SAFI_MULTICAST])
+	    peer->afc_nego[AFI_IP][SAFI_MULTICAST] = 1;
+	  else
+	    return -1;
+	}
+      else if (cap->mpc.safi == BGP_SAFI_VPNV4)
+	{
+	  peer->afc_recv[AFI_IP][SAFI_MPLS_VPN] = 1;
+
+	  if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
+	    peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] = 1;
+	  else
+	    return -1;
+	}
+      else
+	return -1;
+    }
+#ifdef HAVE_IPV6
+  else if (ntohs (cap->mpc.afi) == AFI_IP6)
+    {
+      if (cap->mpc.safi == SAFI_UNICAST)
+	{
+	  peer->afc_recv[AFI_IP6][SAFI_UNICAST] = 1;
+
+	  if (peer->afc[AFI_IP6][SAFI_UNICAST])
+	    peer->afc_nego[AFI_IP6][SAFI_UNICAST] = 1;
+	  else
+	    return -1;
+	}
+      else if (cap->mpc.safi == SAFI_MULTICAST)
+	{
+	  peer->afc_recv[AFI_IP6][SAFI_MULTICAST] = 1;
+
+	  if (peer->afc[AFI_IP6][SAFI_MULTICAST])
+	    peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = 1;
+	  else
+	    return -1;
+	}
+      else
+	return -1;
+    }
+#endif /* HAVE_IPV6 */
+  else
+    {
+      /* Unknown Address Family. */
+      return -1;
+    }
+
+  return 0;
+}
+
+void
+bgp_capability_orf_not_support (struct peer *peer, afi_t afi, safi_t safi,
+				u_char type, u_char mode)
+{
+  if (BGP_DEBUG (normal, NORMAL))
+    zlog_info ("%s Addr-family %d/%d has ORF type/mode %d/%d not supported",
+	       peer->host, afi, safi, type, mode);
+}
+
+int
+bgp_capability_orf (struct peer *peer, struct capability *cap,
+		    u_char *pnt)
+{
+  afi_t afi = ntohs(cap->mpc.afi);
+  safi_t safi = cap->mpc.safi;
+  u_char number_of_orfs;
+  u_char type;
+  u_char mode;
+  u_int16_t sm_cap = 0; /* capability send-mode receive */
+  u_int16_t rm_cap = 0; /* capability receive-mode receive */ 
+  int i;
+
+  /* Check length. */
+  if (cap->length < 7)
+    {
+      zlog_info ("%s ORF Capability length error %d",
+		 peer->host, cap->length);
+		 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+      return -1;
+    }
+
+  if (BGP_DEBUG (normal, NORMAL))
+    zlog_info ("%s OPEN has ORF CAP(%s) for afi/safi: %u/%u",
+	       peer->host, (cap->code == CAPABILITY_CODE_ORF ?
+                       "new" : "old"), afi, safi);
+
+  /* Check AFI and SAFI. */
+  if ((afi != AFI_IP && afi != AFI_IP6)
+      || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
+	  && safi != BGP_SAFI_VPNV4))
+    {
+      zlog_info ("%s Addr-family %d/%d not supported. Ignoring the ORF capability",
+                 peer->host, afi, safi);
+      return -1;
+    }
+
+  number_of_orfs = *pnt++;
+
+  for (i = 0 ; i < number_of_orfs ; i++)
+    {
+      type = *pnt++;
+      mode = *pnt++;
+
+      /* ORF Mode error check */
+      if (mode != ORF_MODE_BOTH && mode != ORF_MODE_SEND
+	  && mode != ORF_MODE_RECEIVE)
+	{
+	  bgp_capability_orf_not_support (peer, afi, safi, type, mode);
+	  continue;
+	}
+
+      /* ORF Type and afi/safi error check */
+      if (cap->code == CAPABILITY_CODE_ORF)
+	{
+	  if (type == ORF_TYPE_PREFIX &&
+	      ((afi == AFI_IP && safi == SAFI_UNICAST)
+		|| (afi == AFI_IP && safi == SAFI_MULTICAST)
+		|| (afi == AFI_IP6 && safi == SAFI_UNICAST)))
+	    {
+	      sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV;
+	      rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV;
+	      if (BGP_DEBUG (normal, NORMAL))
+		zlog_info ("%s OPEN has Prefixlist ORF(%d) capability as %s for afi/safi: %d/%d",
+			   peer->host, ORF_TYPE_PREFIX, (mode == ORF_MODE_SEND ? "SEND" :
+			   mode == ORF_MODE_RECEIVE ? "RECEIVE" : "BOTH") , afi, safi);
+	    }
+	  else
+	    {
+	      bgp_capability_orf_not_support (peer, afi, safi, type, mode);
+	      continue;
+	    }
+	}
+      else if (cap->code == CAPABILITY_CODE_ORF_OLD)
+	{
+	  if (type == ORF_TYPE_PREFIX_OLD &&
+	      ((afi == AFI_IP && safi == SAFI_UNICAST)
+		|| (afi == AFI_IP && safi == SAFI_MULTICAST)
+		|| (afi == AFI_IP6 && safi == SAFI_UNICAST)))
+	    {
+	      sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV;
+	      rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV;
+	      if (BGP_DEBUG (normal, NORMAL))
+		zlog_info ("%s OPEN has Prefixlist ORF(%d) capability as %s for afi/safi: %d/%d",
+			   peer->host, ORF_TYPE_PREFIX_OLD, (mode == ORF_MODE_SEND ? "SEND" :
+			   mode == ORF_MODE_RECEIVE ? "RECEIVE" : "BOTH") , afi, safi);
+	    }
+	  else
+	    {
+	      bgp_capability_orf_not_support (peer, afi, safi, type, mode);
+	      continue;
+	    }
+	}
+      else
+	{
+	  bgp_capability_orf_not_support (peer, afi, safi, type, mode);
+	  continue;
+	}
+
+      switch (mode)
+	{
+	  case ORF_MODE_BOTH:
+	    SET_FLAG (peer->af_cap[afi][safi], sm_cap);
+	    SET_FLAG (peer->af_cap[afi][safi], rm_cap);
+	    break;
+	  case ORF_MODE_SEND:
+	    SET_FLAG (peer->af_cap[afi][safi], sm_cap);
+	    break;
+	  case ORF_MODE_RECEIVE:
+	    SET_FLAG (peer->af_cap[afi][safi], rm_cap);
+	    break;
+	}
+    }
+  return 0;
+}
+
+/* Parse given capability. */
+int
+bgp_capability_parse (struct peer *peer, u_char *pnt, u_char length,
+		      u_char **error)
+{
+  int ret;
+  u_char *end;
+  struct capability cap;
+
+  end = pnt + length;
+
+  while (pnt < end)
+    {
+      afi_t afi;
+      safi_t safi;
+
+      /* Fetch structure to the byte stream. */
+      memcpy (&cap, pnt, sizeof (struct capability));
+
+      afi = ntohs(cap.mpc.afi);
+      safi = cap.mpc.safi;
+
+      if (BGP_DEBUG (normal, NORMAL))
+	zlog_info ("%s OPEN has CAPABILITY code: %d, length %d",
+		   peer->host, cap.code, cap.length);
+
+      /* We need at least capability code and capability length. */
+      if (pnt + 2 > end)
+	{
+	  zlog_info ("%s Capability length error", peer->host);
+	  bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+	  return -1;
+	}
+
+      /* Capability length check. */
+      if (pnt + (cap.length + 2) > end)
+	{
+	  zlog_info ("%s Capability length error", peer->host);
+	  bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+	  return -1;
+	}
+
+      /* We know MP Capability Code. */
+      if (cap.code == CAPABILITY_CODE_MP)
+	{
+	  if (BGP_DEBUG (normal, NORMAL))
+	    zlog_info ("%s OPEN has MP_EXT CAP for afi/safi: %u/%u",
+		       peer->host, afi, safi);
+
+	  /* Ignore capability when override-capability is set. */
+	  if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
+	    {
+	      /* Set negotiated value. */
+	      ret = bgp_capability_mp (peer, &cap);
+
+	      /* Unsupported Capability. */
+	      if (ret < 0)
+		{
+		  /* Store return data. */
+		  memcpy (*error, &cap, cap.length + 2);
+		  *error += cap.length + 2;
+		}
+	    }
+	}
+      else if (cap.code == CAPABILITY_CODE_REFRESH
+	       || cap.code == CAPABILITY_CODE_REFRESH_OLD)
+	{
+	  /* Check length. */
+	  if (cap.length != 0)
+	    {
+	      zlog_info ("%s Route Refresh Capability length error %d",
+			 peer->host, cap.length);
+	      bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+	      return -1;
+	    }
+
+	  if (BGP_DEBUG (normal, NORMAL))
+	    zlog_info ("%s OPEN has ROUTE-REFRESH capability(%s) for all address-families",
+		       peer->host,
+		       cap.code == CAPABILITY_CODE_REFRESH_OLD ? "old" : "new");
+
+	  /* BGP refresh capability */
+	  if (cap.code == CAPABILITY_CODE_REFRESH_OLD)
+	    SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
+	  else
+	    SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
+	}
+      else if (cap.code == CAPABILITY_CODE_ORF
+	       || cap.code == CAPABILITY_CODE_ORF_OLD)
+	bgp_capability_orf (peer, &cap, pnt + sizeof (struct capability));
+      else if (cap.code == CAPABILITY_CODE_DYNAMIC)
+	{
+	  /* Check length. */
+	  if (cap.length != 0)
+	    {
+	      zlog_info ("%s Dynamic Capability length error %d",
+			 peer->host, cap.length);
+	      bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+	      return -1;
+	    }
+
+	  if (BGP_DEBUG (normal, NORMAL))
+	    zlog_info ("%s OPEN has DYNAMIC capability", peer->host);
+
+	  SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
+	}
+ 
+      else if (cap.code > 128)
+	{
+	  /* We don't send Notification for unknown vendor specific
+	     capabilities.  It seems reasonable for now...  */
+	  zlog_warn ("%s Vendor specific capability %d",
+		     peer->host, cap.code);
+	}
+      else
+	{
+	  zlog_warn ("%s unrecognized capability code: %d - ignored",
+		     peer->host, cap.code);
+	  memcpy (*error, &cap, cap.length + 2);
+	  *error += cap.length + 2;
+	}
+
+      pnt += cap.length + 2;
+    }
+  return 0;
+}
+
+int
+bgp_auth_parse (struct peer *peer, u_char *pnt, size_t length)
+{
+  bgp_notify_send (peer, 
+		   BGP_NOTIFY_OPEN_ERR, 
+		   BGP_NOTIFY_OPEN_AUTH_FAILURE); 
+  return -1;
+}
+
+int
+strict_capability_same (struct peer *peer)
+{
+  int i, j;
+
+  for (i = AFI_IP; i < AFI_MAX; i++)
+    for (j = SAFI_UNICAST; j < SAFI_MAX; j++)
+      if (peer->afc[i][j] != peer->afc_nego[i][j])
+	return 0;
+  return 1;
+}
+
+/* Parse open option */
+int
+bgp_open_option_parse (struct peer *peer, u_char length, int *capability)
+{
+  int ret;
+  u_char *end;
+  u_char opt_type;
+  u_char opt_length;
+  u_char *pnt;
+  u_char *error;
+  u_char error_data[BGP_MAX_PACKET_SIZE];
+
+  /* Fetch pointer. */
+  pnt = stream_pnt (peer->ibuf);
+
+  ret = 0;
+  opt_type = 0;
+  opt_length = 0;
+  end = pnt + length;
+  error = error_data;
+
+  if (BGP_DEBUG (normal, NORMAL))
+    zlog_info ("%s rcv OPEN w/ OPTION parameter len: %u",
+	       peer->host, length);
+  
+  while (pnt < end) 
+    {
+      /* Check the length. */
+      if (pnt + 2 > end)
+	{
+	  zlog_info ("%s Option length error", peer->host);
+	  bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+	  return -1;
+	}
+
+      /* Fetch option type and length. */
+      opt_type = *pnt++;
+      opt_length = *pnt++;
+      
+      /* Option length check. */
+      if (pnt + opt_length > end)
+	{
+	  zlog_info ("%s Option length error", peer->host);
+	  bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+	  return -1;
+	}
+
+      if (BGP_DEBUG (normal, NORMAL))
+	zlog_info ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u",
+		   peer->host, opt_type,
+		   opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" :
+		   opt_type == BGP_OPEN_OPT_CAP ? "Capability" : "Unknown",
+		   opt_length);
+  
+      switch (opt_type)
+	{
+	case BGP_OPEN_OPT_AUTH:
+	  ret = bgp_auth_parse (peer, pnt, opt_length);
+	  break;
+	case BGP_OPEN_OPT_CAP:
+	  ret = bgp_capability_parse (peer, pnt, opt_length, &error);
+	  *capability = 1;
+	  break;
+	default:
+	  bgp_notify_send (peer, 
+			   BGP_NOTIFY_OPEN_ERR, 
+			   BGP_NOTIFY_OPEN_UNSUP_PARAM); 
+	  ret = -1;
+	  break;
+	}
+
+      /* Parse error.  To accumulate all unsupported capability codes,
+         bgp_capability_parse does not return -1 when encounter
+         unsupported capability code.  To detect that, please check
+         error and erro_data pointer, like below.  */
+      if (ret < 0)
+	return -1;
+
+      /* Forward pointer. */
+      pnt += opt_length;
+    }
+
+  /* All OPEN option is parsed.  Check capability when strict compare
+     flag is enabled.*/
+  if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
+    {
+      /* If Unsupported Capability exists. */
+      if (error != error_data)
+	{
+	  bgp_notify_send_with_data (peer, 
+				     BGP_NOTIFY_OPEN_ERR, 
+				     BGP_NOTIFY_OPEN_UNSUP_CAPBL, 
+				     error_data, error - error_data);
+	  return -1;
+	}
+
+      /* Check local capability does not negotiated with remote
+         peer. */
+      if (! strict_capability_same (peer))
+	{
+	  bgp_notify_send (peer, 
+			   BGP_NOTIFY_OPEN_ERR, 
+			   BGP_NOTIFY_OPEN_UNSUP_CAPBL);
+	  return -1;
+	}
+    }
+
+  /* Check there is no common capability send Unsupported Capability
+     error. */
+  if (*capability && ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
+    {
+      if (! peer->afc_nego[AFI_IP][SAFI_UNICAST] 
+	  && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST]
+	  && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
+	  && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
+	  && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
+	{
+	  plog_err (peer->log, "%s [Error] No common capability", peer->host);
+
+	  if (error != error_data)
+
+	    bgp_notify_send_with_data (peer, 
+				       BGP_NOTIFY_OPEN_ERR, 
+				       BGP_NOTIFY_OPEN_UNSUP_CAPBL, 
+				       error_data, error - error_data);
+	  else
+	    bgp_notify_send (peer, 
+			     BGP_NOTIFY_OPEN_ERR, 
+			     BGP_NOTIFY_OPEN_UNSUP_CAPBL);
+	  return -1;
+	}
+    }
+  return 0;
+}
+
+void
+bgp_open_capability_orf (struct stream *s, struct peer *peer,
+                         afi_t afi, safi_t safi, u_char code)
+{
+  u_char cap_len;
+  u_char orf_len;
+  unsigned long capp;
+  unsigned long orfp;
+  unsigned long numberp;
+  int number_of_orfs = 0;
+
+  if (safi == SAFI_MPLS_VPN)
+    safi = BGP_SAFI_VPNV4;
+
+  stream_putc (s, BGP_OPEN_OPT_CAP);
+  capp = stream_get_putp (s);           /* Set Capability Len Pointer */
+  stream_putc (s, 0);                   /* Capability Length */
+  stream_putc (s, code);                /* Capability Code */
+  orfp = stream_get_putp (s);           /* Set ORF Len Pointer */
+  stream_putc (s, 0);                   /* ORF Length */
+  stream_putw (s, afi);
+  stream_putc (s, 0);
+  stream_putc (s, safi);
+  numberp = stream_get_putp (s);        /* Set Number Pointer */
+  stream_putc (s, 0);                   /* Number of ORFs */
+
+  /* Address Prefix ORF */
+  if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
+      || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
+    {
+      stream_putc (s, (code == CAPABILITY_CODE_ORF ?
+		   ORF_TYPE_PREFIX : ORF_TYPE_PREFIX_OLD));
+
+      if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
+	  && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
+	{
+	  SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
+	  SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
+	  stream_putc (s, ORF_MODE_BOTH);
+	}
+      else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
+	{
+	  SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
+	  stream_putc (s, ORF_MODE_SEND);
+	}
+      else
+	{
+	  SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
+	  stream_putc (s, ORF_MODE_RECEIVE);
+	}
+      number_of_orfs++;
+    }
+
+  /* Total Number of ORFs. */
+  stream_putc_at (s, numberp, number_of_orfs);
+
+  /* Total ORF Len. */
+  orf_len = stream_get_putp (s) - orfp - 1;
+  stream_putc_at (s, orfp, orf_len);
+
+  /* Total Capability Len. */
+  cap_len = stream_get_putp (s) - capp - 1;
+  stream_putc_at (s, capp, cap_len);
+}
+
+/* Fill in capability open option to the packet. */
+void
+bgp_open_capability (struct stream *s, struct peer *peer)
+{
+  u_char len;
+  unsigned long cp;
+  afi_t afi;
+  safi_t safi;
+
+  /* Remember current pointer for Opt Parm Len. */
+  cp = stream_get_putp (s);
+
+  /* Opt Parm Len. */
+  stream_putc (s, 0);
+
+  /* Do not send capability. */
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN) 
+      || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
+    return;
+
+  /* When the peer is IPv4 unicast only, do not send capability. */
+  if (! peer->afc[AFI_IP][SAFI_MULTICAST] 
+      && ! peer->afc[AFI_IP][SAFI_MPLS_VPN]
+      && ! peer->afc[AFI_IP6][SAFI_UNICAST] 
+      && ! peer->afc[AFI_IP6][SAFI_MULTICAST]
+      && CHECK_FLAG (peer->flags, PEER_FLAG_NO_ROUTE_REFRESH_CAP)
+      && ! CHECK_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
+		       PEER_FLAG_ORF_PREFIX_SM)
+      && ! CHECK_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
+		       PEER_FLAG_ORF_PREFIX_RM)
+      && ! CHECK_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
+		       PEER_FLAG_ORF_PREFIX_SM)
+      && ! CHECK_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
+		       PEER_FLAG_ORF_PREFIX_RM)
+      && ! CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
+    return;
+
+  /* IPv4 unicast. */
+  if (peer->afc[AFI_IP][SAFI_UNICAST])
+    {
+      peer->afc_adv[AFI_IP][SAFI_UNICAST] = 1;
+      stream_putc (s, BGP_OPEN_OPT_CAP);
+      stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
+      stream_putc (s, CAPABILITY_CODE_MP);
+      stream_putc (s, CAPABILITY_CODE_MP_LEN);
+      stream_putw (s, AFI_IP);
+      stream_putc (s, 0);
+      stream_putc (s, SAFI_UNICAST);
+    }
+  /* IPv4 multicast. */
+  if (peer->afc[AFI_IP][SAFI_MULTICAST])
+    {
+      peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 1;
+      stream_putc (s, BGP_OPEN_OPT_CAP);
+      stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
+      stream_putc (s, CAPABILITY_CODE_MP);
+      stream_putc (s, CAPABILITY_CODE_MP_LEN);
+      stream_putw (s, AFI_IP);
+      stream_putc (s, 0);
+      stream_putc (s, SAFI_MULTICAST);
+    }
+  /* IPv4 VPN */
+  if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
+    {
+      peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 1;
+      stream_putc (s, BGP_OPEN_OPT_CAP);
+      stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
+      stream_putc (s, CAPABILITY_CODE_MP);
+      stream_putc (s, CAPABILITY_CODE_MP_LEN);
+      stream_putw (s, AFI_IP);
+      stream_putc (s, 0);
+      stream_putc (s, BGP_SAFI_VPNV4);
+    }
+#ifdef HAVE_IPV6
+  /* IPv6 unicast. */
+  if (peer->afc[AFI_IP6][SAFI_UNICAST])
+    {
+      peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 1;
+      stream_putc (s, BGP_OPEN_OPT_CAP);
+      stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
+      stream_putc (s, CAPABILITY_CODE_MP);
+      stream_putc (s, CAPABILITY_CODE_MP_LEN);
+      stream_putw (s, AFI_IP6);
+      stream_putc (s, 0);
+      stream_putc (s, SAFI_UNICAST);
+    }
+  /* IPv6 multicast. */
+  if (peer->afc[AFI_IP6][SAFI_MULTICAST])
+    {
+      peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 1;
+      stream_putc (s, BGP_OPEN_OPT_CAP);
+      stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
+      stream_putc (s, CAPABILITY_CODE_MP);
+      stream_putc (s, CAPABILITY_CODE_MP_LEN);
+      stream_putw (s, AFI_IP6);
+      stream_putc (s, 0);
+      stream_putc (s, SAFI_MULTICAST);
+    }
+#endif /* HAVE_IPV6 */
+
+  /* Route refresh. */
+  if (! CHECK_FLAG (peer->flags, PEER_FLAG_NO_ROUTE_REFRESH_CAP))
+    {
+      SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
+      stream_putc (s, BGP_OPEN_OPT_CAP);
+      stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
+      stream_putc (s, CAPABILITY_CODE_REFRESH_OLD);
+      stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
+      stream_putc (s, BGP_OPEN_OPT_CAP);
+      stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
+      stream_putc (s, CAPABILITY_CODE_REFRESH);
+      stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
+    }
+
+  /* ORF capability. */
+  for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
+    for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
+      if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
+	  || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
+	{
+	  bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF_OLD);
+	  bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF);
+	}
+
+  /* Dynamic capability. */
+  if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
+    {
+      SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
+      stream_putc (s, BGP_OPEN_OPT_CAP);
+      stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
+      stream_putc (s, CAPABILITY_CODE_DYNAMIC);
+      stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN);
+    }
+
+  /* Total Opt Parm Len. */
+  len = stream_get_putp (s) - cp - 1;
+  stream_putc_at (s, cp, len);
+}
diff --git a/bgpd/bgp_open.h b/bgpd/bgp_open.h
new file mode 100644
index 0000000..af7505a
--- /dev/null
+++ b/bgpd/bgp_open.h
@@ -0,0 +1,69 @@
+/* BGP open message handling
+   Copyright (C) 1999 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+/* MP Capability information. */
+struct capability_mp
+{
+  u_int16_t afi;
+  u_char reserved;
+  u_char safi;
+};
+
+/* BGP open message capability. */
+struct capability
+{
+  u_char code;
+  u_char length;
+  struct capability_mp mpc;
+};
+
+/* Multiprotocol Extensions capabilities. */
+#define CAPABILITY_CODE_MP              1
+#define CAPABILITY_CODE_MP_LEN          4
+
+/* Route refresh capabilities. */
+#define CAPABILITY_CODE_REFRESH         2
+#define CAPABILITY_CODE_REFRESH_OLD   128
+#define CAPABILITY_CODE_REFRESH_LEN     0
+
+/* Cooperative Route Filtering Capability.  */
+#define CAPABILITY_CODE_ORF             3 
+#define CAPABILITY_CODE_ORF_OLD       130
+
+/* ORF Type.  */
+#define ORF_TYPE_PREFIX                64 
+#define ORF_TYPE_PREFIX_OLD           128
+
+/* ORF Mode.  */
+#define ORF_MODE_RECEIVE                1 
+#define ORF_MODE_SEND                   2 
+#define ORF_MODE_BOTH                   3 
+
+/* Dynamic capability.  */
+#define CAPABILITY_CODE_DYNAMIC        66
+#define CAPABILITY_CODE_DYNAMIC_LEN     0
+
+/* Capability Message Action.  */
+#define CAPABILITY_ACTION_SET           0
+#define CAPABILITY_ACTION_UNSET         1
+
+int bgp_open_option_parse (struct peer *, u_char, int *);
+void bgp_open_capability (struct stream *, struct peer *);
+void bgp_capability_vty_out (struct vty *, struct peer *);
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
new file mode 100644
index 0000000..48879f3
--- /dev/null
+++ b/bgpd/bgp_packet.c
@@ -0,0 +1,2240 @@
+/* BGP packet management routine.
+   Copyright (C) 1999 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "thread.h"
+#include "stream.h"
+#include "network.h"
+#include "prefix.h"
+#include "command.h"
+#include "log.h"
+#include "memory.h"
+#include "sockunion.h"		/* for inet_ntop () */
+#include "linklist.h"
+#include "plist.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_table.h"
+#include "bgpd/bgp_dump.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_fsm.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_packet.h"
+#include "bgpd/bgp_open.h"
+#include "bgpd/bgp_aspath.h"
+#include "bgpd/bgp_community.h"
+#include "bgpd/bgp_ecommunity.h"
+#include "bgpd/bgp_network.h"
+#include "bgpd/bgp_mplsvpn.h"
+#include "bgpd/bgp_advertise.h"
+
+int stream_put_prefix (struct stream *, struct prefix *);
+
+/* Set up BGP packet marker and packet type. */
+static int
+bgp_packet_set_marker (struct stream *s, u_char type)
+{
+  int i;
+
+  /* Fill in marker. */
+  for (i = 0; i < BGP_MARKER_SIZE; i++)
+    stream_putc (s, 0xff);
+
+  /* Dummy total length. This field is should be filled in later on. */
+  stream_putw (s, 0);
+
+  /* BGP packet type. */
+  stream_putc (s, type);
+
+  /* Return current stream size. */
+  return stream_get_putp (s);
+}
+
+/* Set BGP packet header size entry.  If size is zero then use current
+   stream size. */
+static int
+bgp_packet_set_size (struct stream *s)
+{
+  int cp;
+
+  /* Preserve current pointer. */
+  cp = stream_get_putp (s);
+  stream_set_putp (s, BGP_MARKER_SIZE);
+  stream_putw (s, cp);
+
+  /* Write back current pointer. */
+  stream_set_putp (s, cp);
+
+  return cp;
+}
+
+/* Add new packet to the peer. */
+void
+bgp_packet_add (struct peer *peer, struct stream *s)
+{
+  /* Add packet to the end of list. */
+  stream_fifo_push (peer->obuf, s);
+}
+
+/* Free first packet. */
+void
+bgp_packet_delete (struct peer *peer)
+{
+  stream_free (stream_fifo_pop (peer->obuf));
+}
+
+/* Duplicate packet. */
+struct stream *
+bgp_packet_dup (struct stream *s)
+{
+  struct stream *new;
+
+  new = stream_new (stream_get_endp (s));
+
+  new->endp = s->endp;
+  new->putp = s->putp;
+  new->getp = s->getp;
+
+  memcpy (new->data, s->data, stream_get_endp (s));
+
+  return new;
+}
+
+/* Check file descriptor whether connect is established. */
+static void
+bgp_connect_check (struct peer *peer)
+{
+  int status;
+  int slen;
+  int ret;
+
+  /* Anyway I have to reset read and write thread. */
+  BGP_READ_OFF (peer->t_read);
+  BGP_WRITE_OFF (peer->t_write);
+
+  /* Check file descriptor. */
+  slen = sizeof (status);
+  ret = getsockopt(peer->fd, SOL_SOCKET, SO_ERROR, (void *) &status, &slen);
+
+  /* If getsockopt is fail, this is fatal error. */
+  if (ret < 0)
+    {
+      zlog (peer->log, LOG_INFO, "can't get sockopt for nonblocking connect");
+      BGP_EVENT_ADD (peer, TCP_fatal_error);
+      return;
+    }      
+
+  /* When status is 0 then TCP connection is established. */
+  if (status == 0)
+    {
+      BGP_EVENT_ADD (peer, TCP_connection_open);
+    }
+  else
+    {
+      if (BGP_DEBUG (events, EVENTS))
+	  plog_info (peer->log, "%s [Event] Connect failed (%s)",
+		     peer->host, strerror (errno));
+      BGP_EVENT_ADD (peer, TCP_connection_open_failed);
+    }
+}
+
+/* Make BGP update packet.  */
+struct stream *
+bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
+{
+  struct stream *s;
+  struct bgp_adj_out *adj;
+  struct bgp_advertise *adv;
+  struct stream *packet;
+  struct bgp_node *rn = NULL;
+  struct bgp_info *binfo = NULL;
+  bgp_size_t total_attr_len = 0;
+  unsigned long pos;
+  char buf[BUFSIZ];
+  struct prefix_rd *prd = NULL;
+  char *tag = NULL;
+
+  s = peer->work;
+  stream_reset (s);
+
+  adv = FIFO_HEAD (&peer->sync[afi][safi]->update);
+
+  while (adv)
+    {
+      if (adv->rn)
+        rn = adv->rn;
+      adj = adv->adj;
+      if (adv->binfo)
+        binfo = adv->binfo;
+#ifdef MPLS_VPN
+      if (rn)
+        prd = (struct prefix_rd *) &rn->prn->p;
+      if (binfo)
+        tag = binfo->tag;
+#endif /* MPLS_VPN */
+
+      /* When remaining space can't include NLRI and it's length.  */
+      if (rn && STREAM_REMAIN (s) <= BGP_NLRI_LENGTH + PSIZE (rn->p.prefixlen))
+	break;
+
+      /* If packet is empty, set attribute. */
+      if (stream_empty (s))
+	{
+	  bgp_packet_set_marker (s, BGP_MSG_UPDATE);
+	  stream_putw (s, 0);		
+	  pos = stream_get_putp (s);
+	  stream_putw (s, 0);
+	  total_attr_len = bgp_packet_attribute (NULL, peer, s,
+	                			 adv->baa->attr,
+						 &rn->p, afi, safi,
+						 binfo->peer, prd, tag);
+	  stream_putw_at (s, pos, total_attr_len);
+	}
+
+      if (afi == AFI_IP && safi == SAFI_UNICAST)
+	stream_put_prefix (s, &rn->p);
+      
+      if (BGP_DEBUG (update, UPDATE_OUT))
+	zlog (peer->log, LOG_INFO, "%s send UPDATE %s/%d",
+	      peer->host,
+	      inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, BUFSIZ),
+	      rn->p.prefixlen);
+
+      /* Synchnorize attribute.  */
+      if (adj->attr)
+	bgp_attr_unintern (adj->attr);
+      else
+	peer->scount[afi][safi]++;
+
+      adj->attr = bgp_attr_intern (adv->baa->attr);
+
+      adv = bgp_advertise_clean (peer, adj, afi, safi);
+
+      if (! (afi == AFI_IP && safi == SAFI_UNICAST))
+	break;
+    }
+	 
+  if (! stream_empty (s))
+    {
+      bgp_packet_set_size (s);
+      packet = bgp_packet_dup (s);
+      bgp_packet_add (peer, packet);
+      BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+      stream_reset (s);
+      return packet;
+    }
+  return NULL;
+
+}
+
+/* Make BGP withdraw packet.  */
+struct stream *
+bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
+{
+  struct stream *s;
+  struct stream *packet;
+  struct bgp_adj_out *adj;
+  struct bgp_advertise *adv;
+  struct bgp_node *rn;
+  unsigned long pos;
+  bgp_size_t unfeasible_len;
+  bgp_size_t total_attr_len;
+  char buf[BUFSIZ];
+  struct prefix_rd *prd = NULL;
+
+  s = peer->work;
+  stream_reset (s);
+
+  while ((adv = FIFO_HEAD (&peer->sync[afi][safi]->withdraw)) != NULL)
+    {
+      adj = adv->adj;
+      rn = adv->rn;
+#ifdef MPLS_VPN
+      prd = (struct prefix_rd *) &rn->prn->p;
+#endif /* MPLS_VPN */
+
+      if (STREAM_REMAIN (s) 
+	  <= (BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN + PSIZE (rn->p.prefixlen)))
+	break;
+
+      if (stream_empty (s))
+	{
+	  bgp_packet_set_marker (s, BGP_MSG_UPDATE);
+	  stream_putw (s, 0);
+	}
+
+      if (afi == AFI_IP && safi == SAFI_UNICAST)
+	stream_put_prefix (s, &rn->p);
+      else
+	{
+	  pos = stream_get_putp (s);
+	  stream_putw (s, 0);
+	  total_attr_len
+	    = bgp_packet_withdraw (peer, s, &rn->p, afi, safi, prd, NULL);
+      
+	  /* Set total path attribute length. */
+	  stream_putw_at (s, pos, total_attr_len);
+	}
+
+      if (BGP_DEBUG (update, UPDATE_OUT))
+	zlog (peer->log, LOG_INFO, "%s send UPDATE %s/%d -- unreachable",
+	      peer->host,
+	      inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, BUFSIZ),
+	      rn->p.prefixlen);
+
+      peer->scount[afi][safi]--;
+
+      bgp_adj_out_remove (rn, adj, peer, afi, safi);
+      bgp_unlock_node (rn);
+
+      if (! (afi == AFI_IP && safi == SAFI_UNICAST))
+	break;
+    }
+
+  if (! stream_empty (s))
+    {
+      if (afi == AFI_IP && safi == SAFI_UNICAST)
+	{
+	  unfeasible_len 
+	    = stream_get_putp (s) - BGP_HEADER_SIZE - BGP_UNFEASIBLE_LEN;
+	  stream_putw_at (s, BGP_HEADER_SIZE, unfeasible_len);
+	  stream_putw (s, 0);
+	}
+      bgp_packet_set_size (s);
+      packet = bgp_packet_dup (s);
+      bgp_packet_add (peer, packet);
+      stream_reset (s);
+      return packet;
+    }
+
+  return NULL;
+}
+
+void
+bgp_default_update_send (struct peer *peer, struct attr *attr,
+			 afi_t afi, safi_t safi, struct peer *from)
+{
+  struct stream *s;
+  struct stream *packet;
+  struct prefix p;
+  unsigned long pos;
+  bgp_size_t total_attr_len;
+  char attrstr[BUFSIZ];
+  char buf[BUFSIZ];
+
+#ifdef DISABLE_BGP_ANNOUNCE
+  return;
+#endif /* DISABLE_BGP_ANNOUNCE */
+
+  if (afi == AFI_IP)
+    str2prefix ("0.0.0.0/0", &p);
+#ifdef HAVE_IPV6
+  else 
+    str2prefix ("::/0", &p);
+#endif /* HAVE_IPV6 */
+
+  /* Logging the attribute. */
+  if (BGP_DEBUG (update, UPDATE_OUT))
+    {
+      bgp_dump_attr (peer, attr, attrstr, BUFSIZ);
+      zlog (peer->log, LOG_INFO, "%s send UPDATE %s/%d %s",
+	    peer->host, inet_ntop(p.family, &(p.u.prefix), buf, BUFSIZ),
+	    p.prefixlen, attrstr);
+    }
+
+  s = stream_new (BGP_MAX_PACKET_SIZE);
+
+  /* Make BGP update packet. */
+  bgp_packet_set_marker (s, BGP_MSG_UPDATE);
+
+  /* Unfeasible Routes Length. */
+  stream_putw (s, 0);
+
+  /* Make place for total attribute length.  */
+  pos = stream_get_putp (s);
+  stream_putw (s, 0);
+  total_attr_len = bgp_packet_attribute (NULL, peer, s, attr, &p, afi, safi, from, NULL, NULL);
+
+  /* Set Total Path Attribute Length. */
+  stream_putw_at (s, pos, total_attr_len);
+
+  /* NLRI set. */
+  if (p.family == AF_INET && safi == SAFI_UNICAST)
+    stream_put_prefix (s, &p);
+
+  /* Set size. */
+  bgp_packet_set_size (s);
+
+  packet = bgp_packet_dup (s);
+  stream_free (s);
+
+  /* Dump packet if debug option is set. */
+#ifdef DEBUG
+  bgp_packet_dump (packet);
+#endif /* DEBUG */
+
+  /* Add packet to the peer. */
+  bgp_packet_add (peer, packet);
+
+  BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+}
+
+void
+bgp_default_withdraw_send (struct peer *peer, afi_t afi, safi_t safi)
+{
+  struct stream *s;
+  struct stream *packet;
+  struct prefix p;
+  unsigned long pos;
+  unsigned long cp;
+  bgp_size_t unfeasible_len;
+  bgp_size_t total_attr_len;
+  char buf[BUFSIZ];
+
+#ifdef DISABLE_BGP_ANNOUNCE
+  return;
+#endif /* DISABLE_BGP_ANNOUNCE */
+
+  if (afi == AFI_IP)
+    str2prefix ("0.0.0.0/0", &p);
+#ifdef HAVE_IPV6
+  else 
+    str2prefix ("::/0", &p);
+#endif /* HAVE_IPV6 */
+
+  total_attr_len = 0;
+  pos = 0;
+
+  if (BGP_DEBUG (update, UPDATE_OUT))
+    zlog (peer->log, LOG_INFO, "%s send UPDATE %s/%d -- unreachable",
+          peer->host, inet_ntop(p.family, &(p.u.prefix), buf, BUFSIZ),
+          p.prefixlen);
+
+  s = stream_new (BGP_MAX_PACKET_SIZE);
+
+  /* Make BGP update packet. */
+  bgp_packet_set_marker (s, BGP_MSG_UPDATE);
+
+  /* Unfeasible Routes Length. */;
+  cp = stream_get_putp (s);
+  stream_putw (s, 0);
+
+  /* Withdrawn Routes. */
+  if (p.family == AF_INET && safi == SAFI_UNICAST)
+    {
+      stream_put_prefix (s, &p);
+
+      unfeasible_len = stream_get_putp (s) - cp - 2;
+
+      /* Set unfeasible len.  */
+      stream_putw_at (s, cp, unfeasible_len);
+
+      /* Set total path attribute length. */
+      stream_putw (s, 0);
+    }
+  else
+    {
+      pos = stream_get_putp (s);
+      stream_putw (s, 0);
+      total_attr_len = bgp_packet_withdraw (peer, s, &p, afi, safi, NULL, NULL);
+
+      /* Set total path attribute length. */
+      stream_putw_at (s, pos, total_attr_len);
+    }
+
+  bgp_packet_set_size (s);
+
+  packet = bgp_packet_dup (s);
+  stream_free (s);
+
+  /* Add packet to the peer. */
+  bgp_packet_add (peer, packet);
+
+  BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+}
+
+/* Get next packet to be written.  */
+struct stream *
+bgp_write_packet (struct peer *peer)
+{
+  afi_t afi;
+  safi_t safi;
+  struct stream *s = NULL;
+  struct bgp_advertise *adv;
+
+  s = stream_fifo_head (peer->obuf);
+  if (s)
+    return s;
+
+  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+      {
+	adv = FIFO_HEAD (&peer->sync[afi][safi]->withdraw);
+	if (adv)
+	  {
+	    s = bgp_withdraw_packet (peer, afi, safi);
+	    if (s)
+	      return s;
+	  }
+      }
+    
+  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+      {
+	adv = FIFO_HEAD (&peer->sync[afi][safi]->update);
+	if (adv)
+	  {
+            if (adv->binfo && adv->binfo->uptime < peer->synctime)
+              s = bgp_update_packet (peer, afi, safi);
+
+	    if (s)
+	      return s;
+	  }
+      }
+
+  return NULL;
+}
+
+/* Is there partially written packet or updates we can send right
+   now.  */
+int
+bgp_write_proceed (struct peer *peer)
+{
+  afi_t afi;
+  safi_t safi;
+  struct bgp_advertise *adv;
+
+  if (stream_fifo_head (peer->obuf))
+    return 1;
+
+  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+      if (FIFO_HEAD (&peer->sync[afi][safi]->withdraw))
+	return 1;
+
+  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+      if ((adv = FIFO_HEAD (&peer->sync[afi][safi]->update)) != NULL)
+	if (adv->binfo->uptime < peer->synctime)
+	  return 1;
+
+  return 0;
+}
+
+/* Write packet to the peer. */
+int
+bgp_write (struct thread *thread)
+{
+  struct peer *peer;
+  u_char type;
+  struct stream *s; 
+  int num;
+  int count = 0;
+  int write_errno;
+
+  /* Yes first of all get peer pointer. */
+  peer = THREAD_ARG (thread);
+  peer->t_write = NULL;
+
+  /* For non-blocking IO check. */
+  if (peer->status == Connect)
+    {
+      bgp_connect_check (peer);
+      return 0;
+    }
+
+    /* Nonblocking write until TCP output buffer is full.  */
+  while (1)
+    {
+      int writenum;
+
+      s = bgp_write_packet (peer);
+      if (! s)
+	return 0;
+
+      /* Number of bytes to be sent.  */
+      writenum = stream_get_endp (s) - stream_get_getp (s);
+
+      /* Call write() system call.  */
+      num = write (peer->fd, STREAM_PNT (s), writenum);
+      write_errno = errno;
+      if (num <= 0)
+	{
+	  /* Partial write. */
+	  if (write_errno == EWOULDBLOCK || write_errno == EAGAIN)
+	      break;
+
+	  bgp_stop (peer);
+	  peer->status = Idle;
+	  bgp_timer_set (peer);
+	  return 0;
+	}
+      if (num != writenum)
+	{
+	  stream_forward (s, num);
+
+	  if (write_errno == EAGAIN)
+	    break;
+
+	  continue;
+	}
+
+      /* Retrieve BGP packet type. */
+      stream_set_getp (s, BGP_MARKER_SIZE + 2);
+      type = stream_getc (s);
+
+      switch (type)
+	{
+	case BGP_MSG_OPEN:
+	  peer->open_out++;
+	  break;
+	case BGP_MSG_UPDATE:
+	  peer->update_out++;
+	  break;
+	case BGP_MSG_NOTIFY:
+	  peer->notify_out++;
+	  /* Double start timer. */
+	  peer->v_start *= 2;
+
+	  /* Overflow check. */
+	  if (peer->v_start >= (60 * 2))
+	    peer->v_start = (60 * 2);
+
+	  /* BGP_EVENT_ADD (peer, BGP_Stop); */
+	  bgp_stop (peer);
+	  peer->status = Idle;
+	  bgp_timer_set (peer);
+	  return 0;
+	  break;
+	case BGP_MSG_KEEPALIVE:
+	  peer->keepalive_out++;
+	  break;
+	case BGP_MSG_ROUTE_REFRESH_NEW:
+	case BGP_MSG_ROUTE_REFRESH_OLD:
+	  peer->refresh_out++;
+	  break;
+	case BGP_MSG_CAPABILITY:
+	  peer->dynamic_cap_out++;
+	  break;
+	}
+
+      /* OK we send packet so delete it. */
+      bgp_packet_delete (peer);
+
+      if (++count >= BGP_WRITE_PACKET_MAX)
+	break;
+    }
+  
+  if (bgp_write_proceed (peer))
+    BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+  
+  return 0;
+}
+
+/* This is only for sending NOTIFICATION message to neighbor. */
+int
+bgp_write_notify (struct peer *peer)
+{
+  int ret;
+  u_char type;
+  struct stream *s; 
+
+  /* There should be at least one packet. */
+  s = stream_fifo_head (peer->obuf);
+  if (!s)
+    return 0;
+  assert (stream_get_endp (s) >= BGP_HEADER_SIZE);
+
+  /* I'm not sure fd is writable. */
+  ret = writen (peer->fd, STREAM_DATA (s), stream_get_endp (s));
+  if (ret <= 0)
+    {
+      bgp_stop (peer);
+      peer->status = Idle;
+      bgp_timer_set (peer);
+      return 0;
+    }
+
+  /* Retrieve BGP packet type. */
+  stream_set_getp (s, BGP_MARKER_SIZE + 2);
+  type = stream_getc (s);
+
+  assert (type == BGP_MSG_NOTIFY);
+
+  /* Type should be notify. */
+  peer->notify_out++;
+
+  /* Double start timer. */
+  peer->v_start *= 2;
+
+  /* Overflow check. */
+  if (peer->v_start >= (60 * 2))
+    peer->v_start = (60 * 2);
+
+  /* We don't call event manager at here for avoiding other events. */
+  bgp_stop (peer);
+  peer->status = Idle;
+  bgp_timer_set (peer);
+
+  return 0;
+}
+
+/* Make keepalive packet and send it to the peer. */
+void
+bgp_keepalive_send (struct peer *peer)
+{
+  struct stream *s;
+  int length;
+
+  s = stream_new (BGP_MAX_PACKET_SIZE);
+
+  /* Make keepalive packet. */
+  bgp_packet_set_marker (s, BGP_MSG_KEEPALIVE);
+
+  /* Set packet size. */
+  length = bgp_packet_set_size (s);
+
+  /* Dump packet if debug option is set. */
+  /* bgp_packet_dump (s); */
+ 
+  if (BGP_DEBUG (keepalive, KEEPALIVE))  
+    zlog_info ("%s sending KEEPALIVE", peer->host); 
+  if (BGP_DEBUG (normal, NORMAL))
+    zlog_info ("%s send message type %d, length (incl. header) %d",
+               peer->host, BGP_MSG_KEEPALIVE, length);
+
+  /* Add packet to the peer. */
+  bgp_packet_add (peer, s);
+
+  BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+}
+
+/* Make open packet and send it to the peer. */
+void
+bgp_open_send (struct peer *peer)
+{
+  struct stream *s;
+  int length;
+  u_int16_t send_holdtime;
+  as_t local_as;
+
+  if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
+    send_holdtime = peer->holdtime;
+  else
+    send_holdtime = peer->bgp->default_holdtime;
+
+  /* local-as Change */
+  if (peer->change_local_as)
+    local_as = peer->change_local_as; 
+  else
+    local_as = peer->local_as; 
+
+  s = stream_new (BGP_MAX_PACKET_SIZE);
+
+  /* Make open packet. */
+  bgp_packet_set_marker (s, BGP_MSG_OPEN);
+
+  /* Set open packet values. */
+  stream_putc (s, BGP_VERSION_4);        /* BGP version */
+  stream_putw (s, local_as);		 /* My Autonomous System*/
+  stream_putw (s, send_holdtime);     	 /* Hold Time */
+  stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */
+
+  /* Set capability code. */
+  bgp_open_capability (s, peer);
+
+  /* Set BGP packet length. */
+  length = bgp_packet_set_size (s);
+
+  if (BGP_DEBUG (normal, NORMAL))
+    zlog_info ("%s sending OPEN, version %d, my as %d, holdtime %d, id %s", 
+	       peer->host, BGP_VERSION_4, local_as,
+	       send_holdtime, inet_ntoa (peer->local_id));
+
+  if (BGP_DEBUG (normal, NORMAL))
+    zlog_info ("%s send message type %d, length (incl. header) %d",
+	       peer->host, BGP_MSG_OPEN, length);
+
+  /* Dump packet if debug option is set. */
+  /* bgp_packet_dump (s); */
+
+  /* Add packet to the peer. */
+  bgp_packet_add (peer, s);
+
+  BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+}
+
+/* Send BGP notify packet with data potion. */
+void
+bgp_notify_send_with_data (struct peer *peer, u_char code, u_char sub_code,
+			   u_char *data, size_t datalen)
+{
+  struct stream *s;
+  int length;
+
+  /* Allocate new stream. */
+  s = stream_new (BGP_MAX_PACKET_SIZE);
+
+  /* Make nitify packet. */
+  bgp_packet_set_marker (s, BGP_MSG_NOTIFY);
+
+  /* Set notify packet values. */
+  stream_putc (s, code);        /* BGP notify code */
+  stream_putc (s, sub_code);	/* BGP notify sub_code */
+
+  /* If notify data is present. */
+  if (data)
+    stream_write (s, data, datalen);
+  
+  /* Set BGP packet length. */
+  length = bgp_packet_set_size (s);
+  
+  /* Add packet to the peer. */
+  stream_fifo_clean (peer->obuf);
+  bgp_packet_add (peer, s);
+
+  /* For debug */
+  {
+    struct bgp_notify bgp_notify;
+    int first = 0;
+    int i;
+    char c[4];
+
+    bgp_notify.code = code;
+    bgp_notify.subcode = sub_code;
+    bgp_notify.data = NULL;
+    bgp_notify.length = length - BGP_MSG_NOTIFY_MIN_SIZE;
+    
+    if (bgp_notify.length)
+      {
+	bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
+	for (i = 0; i < bgp_notify.length; i++)
+	  if (first)
+	    {
+	      sprintf (c, " %02x", data[i]);
+	      strcat (bgp_notify.data, c);
+	    }
+	  else
+	    {
+	      first = 1;
+	      sprintf (c, "%02x", data[i]);
+	      strcpy (bgp_notify.data, c);
+	    }
+      }
+    bgp_notify_print (peer, &bgp_notify, "sending");
+    if (bgp_notify.data)
+      XFREE (MTYPE_TMP, bgp_notify.data);
+  }
+
+  if (BGP_DEBUG (normal, NORMAL))
+    zlog_info ("%s send message type %d, length (incl. header) %d",
+	       peer->host, BGP_MSG_NOTIFY, length);
+
+  /* Call imidiately. */
+  BGP_WRITE_OFF (peer->t_write);
+
+  bgp_write_notify (peer);
+}
+
+/* Send BGP notify packet. */
+void
+bgp_notify_send (struct peer *peer, u_char code, u_char sub_code)
+{
+  bgp_notify_send_with_data (peer, code, sub_code, NULL, 0);
+}
+
+char *
+afi2str (afi_t afi)
+{
+  if (afi == AFI_IP)
+    return "AFI_IP";
+  else if (afi == AFI_IP6)
+    return "AFI_IP6";
+  else
+    return "Unknown AFI";
+}
+
+char *
+safi2str (safi_t safi)
+{
+  if (safi == SAFI_UNICAST)
+    return "SAFI_UNICAST";
+  else if (safi == SAFI_MULTICAST)
+    return "SAFI_MULTICAST";
+  else if (safi == SAFI_MPLS_VPN || safi == BGP_SAFI_VPNV4)
+    return "SAFI_MPLS_VPN";
+  else
+    return "Unknown SAFI";
+}
+
+/* Send route refresh message to the peer. */
+void
+bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
+			u_char orf_type, u_char when_to_refresh, int remove)
+{
+  struct stream *s;
+  struct stream *packet;
+  int length;
+  struct bgp_filter *filter;
+  int orf_refresh = 0;
+
+#ifdef DISABLE_BGP_ANNOUNCE
+  return;
+#endif /* DISABLE_BGP_ANNOUNCE */
+
+  filter = &peer->filter[afi][safi];
+
+  /* Adjust safi code. */
+  if (safi == SAFI_MPLS_VPN)
+    safi = BGP_SAFI_VPNV4;
+  
+  s = stream_new (BGP_MAX_PACKET_SIZE);
+
+  /* Make BGP update packet. */
+  if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
+    bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_NEW);
+  else
+    bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_OLD);
+
+  /* Encode Route Refresh message. */
+  stream_putw (s, afi);
+  stream_putc (s, 0);
+  stream_putc (s, safi);
+ 
+  if (orf_type == ORF_TYPE_PREFIX
+      || orf_type == ORF_TYPE_PREFIX_OLD)
+    if (remove || filter->plist[FILTER_IN].plist)
+      {
+	u_int16_t orf_len;
+	unsigned long orfp;
+
+	orf_refresh = 1; 
+	stream_putc (s, when_to_refresh);
+	stream_putc (s, orf_type);
+	orfp = stream_get_putp (s);
+	stream_putw (s, 0);
+
+	if (remove)
+	  {
+	    UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
+	    stream_putc (s, ORF_COMMON_PART_REMOVE_ALL);
+	    if (BGP_DEBUG (normal, NORMAL))
+	      zlog_info ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d", 
+			 peer->host, orf_type,
+			 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
+			 afi, safi);
+	  }
+	else
+	  {
+	    SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
+	    prefix_bgp_orf_entry (s, filter->plist[FILTER_IN].plist,
+				  ORF_COMMON_PART_ADD, ORF_COMMON_PART_PERMIT,
+				  ORF_COMMON_PART_DENY);
+	    if (BGP_DEBUG (normal, NORMAL))
+	      zlog_info ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d", 
+			 peer->host, orf_type,
+			 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
+			 afi, safi);
+	  }
+
+	/* Total ORF Entry Len. */
+	orf_len = stream_get_putp (s) - orfp - 2;
+	stream_putw_at (s, orfp, orf_len);
+      }
+
+  /* Set packet size. */
+  length = bgp_packet_set_size (s);
+
+  if (BGP_DEBUG (normal, NORMAL))
+    {
+      if (! orf_refresh)
+	zlog_info ("%s sending REFRESH_REQ for afi/safi: %d/%d", 
+		   peer->host, afi, safi);
+      zlog_info ("%s send message type %d, length (incl. header) %d",
+		 peer->host, CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV) ?
+		 BGP_MSG_ROUTE_REFRESH_NEW : BGP_MSG_ROUTE_REFRESH_OLD, length);
+    }
+
+  /* Make real packet. */
+  packet = bgp_packet_dup (s);
+  stream_free (s);
+
+  /* Add packet to the peer. */
+  bgp_packet_add (peer, packet);
+
+  BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+}
+
+/* Send capability message to the peer. */
+void
+bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
+		     int capability_code, int action)
+{
+  struct stream *s;
+  struct stream *packet;
+  int length;
+
+  /* Adjust safi code. */
+  if (safi == SAFI_MPLS_VPN)
+    safi = BGP_SAFI_VPNV4;
+
+  s = stream_new (BGP_MAX_PACKET_SIZE);
+
+  /* Make BGP update packet. */
+  bgp_packet_set_marker (s, BGP_MSG_CAPABILITY);
+
+  /* Encode MP_EXT capability. */
+  if (capability_code == CAPABILITY_CODE_MP)
+    {
+      stream_putc (s, action);
+      stream_putc (s, CAPABILITY_CODE_MP);
+      stream_putc (s, CAPABILITY_CODE_MP_LEN);
+      stream_putw (s, afi);
+      stream_putc (s, 0);
+      stream_putc (s, safi);
+
+      if (BGP_DEBUG (normal, NORMAL))
+        zlog_info ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d",
+		   peer->host, action == CAPABILITY_ACTION_SET ?
+		   "Advertising" : "Removing", afi, safi);
+    }
+
+  /* Encode Route Refresh capability. */
+  if (capability_code == CAPABILITY_CODE_REFRESH)
+    {
+      stream_putc (s, action);
+      stream_putc (s, CAPABILITY_CODE_REFRESH);
+      stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
+      stream_putc (s, action);
+      stream_putc (s, CAPABILITY_CODE_REFRESH_OLD);
+      stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
+
+      if (BGP_DEBUG (normal, NORMAL))
+        zlog_info ("%s sending CAPABILITY has %s ROUTE-REFRESH capability",
+		   peer->host, action == CAPABILITY_ACTION_SET ?
+		   "Advertising" : "Removing");
+    }
+
+  /* Set packet size. */
+  length = bgp_packet_set_size (s);
+
+  /* Make real packet. */
+  packet = bgp_packet_dup (s);
+  stream_free (s);
+
+  /* Add packet to the peer. */
+  bgp_packet_add (peer, packet);
+
+  if (BGP_DEBUG (normal, NORMAL))
+    zlog_info ("%s send message type %d, length (incl. header) %d",
+	       peer->host, BGP_MSG_CAPABILITY, length);
+
+  BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+}
+
+/* RFC1771 6.8 Connection collision detection. */
+int
+bgp_collision_detect (struct peer *new, struct in_addr remote_id)
+{
+  struct peer *peer;
+  struct listnode *nn;
+  struct bgp *bgp;
+
+  bgp = bgp_get_default ();
+  if (! bgp)
+    return 0;
+  
+  /* Upon receipt of an OPEN message, the local system must examine
+     all of its connections that are in the OpenConfirm state.  A BGP
+     speaker may also examine connections in an OpenSent state if it
+     knows the BGP Identifier of the peer by means outside of the
+     protocol.  If among these connections there is a connection to a
+     remote BGP speaker whose BGP Identifier equals the one in the
+     OPEN message, then the local system performs the following
+     collision resolution procedure: */
+
+  LIST_LOOP (bgp->peer, peer, nn)
+    {
+      /* Under OpenConfirm status, local peer structure already hold
+         remote router ID. */
+
+      if (peer != new
+	  && (peer->status == OpenConfirm || peer->status == OpenSent)
+	  && sockunion_same (&peer->su, &new->su))
+	{
+	  /* 1. The BGP Identifier of the local system is compared to
+	     the BGP Identifier of the remote system (as specified in
+	     the OPEN message). */
+
+	  if (ntohl (peer->local_id.s_addr) < ntohl (remote_id.s_addr))
+	    {
+	      /* 2. If the value of the local BGP Identifier is less
+		 than the remote one, the local system closes BGP
+		 connection that already exists (the one that is
+		 already in the OpenConfirm state), and accepts BGP
+		 connection initiated by the remote system. */
+
+	      if (peer->fd >= 0)
+		bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+	      return 1;
+	    }
+	  else
+	    {
+	      /* 3. Otherwise, the local system closes newly created
+		 BGP connection (the one associated with the newly
+		 received OPEN message), and continues to use the
+		 existing one (the one that is already in the
+		 OpenConfirm state). */
+
+	      if (new->fd >= 0)
+		bgp_notify_send (new, BGP_NOTIFY_CEASE, 0);
+	      return -1;
+	    }
+	}
+    }
+  return 0;
+}
+
+int
+bgp_open_receive (struct peer *peer, bgp_size_t size)
+{
+  int ret;
+  u_char version;
+  u_char optlen;
+  u_int16_t holdtime;
+  u_int16_t send_holdtime;
+  as_t remote_as;
+  struct peer *realpeer;
+  struct in_addr remote_id;
+  int capability;
+  char notify_data_remote_as[2];
+  char notify_data_remote_id[4];
+
+  realpeer = NULL;
+  
+  /* Parse open packet. */
+  version = stream_getc (peer->ibuf);
+  memcpy (notify_data_remote_as, stream_pnt (peer->ibuf), 2);
+  remote_as  = stream_getw (peer->ibuf);
+  holdtime = stream_getw (peer->ibuf);
+  memcpy (notify_data_remote_id, stream_pnt (peer->ibuf), 4);
+  remote_id.s_addr = stream_get_ipv4 (peer->ibuf);
+
+  /* Receive OPEN message log  */
+  if (BGP_DEBUG (normal, NORMAL))
+    zlog_info ("%s rcv OPEN, version %d, remote-as %d, holdtime %d, id %s",
+	       peer->host, version, remote_as, holdtime,
+	       inet_ntoa (remote_id));
+	  
+  /* Lookup peer from Open packet. */
+  if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
+    {
+      int as = 0;
+
+      realpeer = peer_lookup_with_open (&peer->su, remote_as, &remote_id, &as);
+
+      if (! realpeer)
+	{
+	  /* Peer's source IP address is check in bgp_accept(), so this
+	     must be AS number mismatch or remote-id configuration
+	     mismatch. */
+	  if (as)
+	    {
+	      if (BGP_DEBUG (normal, NORMAL))
+		zlog_info ("%s bad OPEN, wrong router identifier %s",
+			   peer->host, inet_ntoa (remote_id));
+	      bgp_notify_send_with_data (peer, 
+					 BGP_NOTIFY_OPEN_ERR, 
+					 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
+					 notify_data_remote_id, 4);
+	    }
+	  else
+	    {
+	      if (BGP_DEBUG (normal, NORMAL))
+		zlog_info ("%s bad OPEN, remote AS is %d, expected %d",
+			   peer->host, remote_as, peer->as);
+	      bgp_notify_send_with_data (peer, 
+					 BGP_NOTIFY_OPEN_ERR, 
+					 BGP_NOTIFY_OPEN_BAD_PEER_AS,
+					 notify_data_remote_as, 2);
+	    }
+	  return -1;
+	}
+    }
+
+  /* When collision is detected and this peer is closed.  Retrun
+     immidiately. */
+  ret = bgp_collision_detect (peer, remote_id);
+  if (ret < 0)
+    return ret;
+
+  /* Hack part. */
+  if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
+    {
+      if (ret == 0 && realpeer->status != Active
+	  && realpeer->status != OpenSent
+	  && realpeer->status != OpenConfirm)
+ 	{
+ 	  if (BGP_DEBUG (events, EVENTS))
+ 	    zlog_info ("%s [Event] peer's status is %s close connection",
+		       realpeer->host, LOOKUP (bgp_status_msg, peer->status));
+ 	  return -1;
+ 	}
+
+      if (BGP_DEBUG (events, EVENTS))
+	zlog_info ("%s [Event] Transfer temporary BGP peer to existing one",
+		   peer->host);
+
+      bgp_stop (realpeer);
+      
+      /* Transfer file descriptor. */
+      realpeer->fd = peer->fd;
+      peer->fd = -1;
+
+      /* Transfer input buffer. */
+      stream_free (realpeer->ibuf);
+      realpeer->ibuf = peer->ibuf;
+      realpeer->packet_size = peer->packet_size;
+      peer->ibuf = NULL;
+
+      /* Transfer status. */
+      realpeer->status = peer->status;
+      bgp_stop (peer);
+
+      /* peer pointer change. Open packet send to neighbor. */
+      peer = realpeer;
+      bgp_open_send (peer);
+      if (peer->fd < 0)
+	{
+	  zlog_err ("bgp_open_receive peer's fd is negative value %d",
+		    peer->fd);
+	  return -1;
+	}
+      BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
+    }
+
+  /* remote router-id check. */
+  if (remote_id.s_addr == 0
+      || ntohl (remote_id.s_addr) >= 0xe0000000
+      || ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr))
+    {
+      if (BGP_DEBUG (normal, NORMAL))
+	zlog_info ("%s bad OPEN, wrong router identifier %s",
+		   peer->host, inet_ntoa (remote_id));
+      bgp_notify_send_with_data (peer, 
+				 BGP_NOTIFY_OPEN_ERR, 
+				 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
+				 notify_data_remote_id, 4);
+      return -1;
+    }
+
+  /* Set remote router-id */
+  peer->remote_id = remote_id;
+
+  /* Peer BGP version check. */
+  if (version != BGP_VERSION_4)
+    {
+      if (BGP_DEBUG (normal, NORMAL))
+	zlog_info ("%s bad protocol version, remote requested %d, local request %d",
+		   peer->host, version, BGP_VERSION_4);
+      bgp_notify_send_with_data (peer, 
+				 BGP_NOTIFY_OPEN_ERR, 
+				 BGP_NOTIFY_OPEN_UNSUP_VERSION,
+				 "\x04", 1);
+      return -1;
+    }
+
+  /* Check neighbor as number. */
+  if (remote_as != peer->as)
+    {
+      if (BGP_DEBUG (normal, NORMAL))
+	zlog_info ("%s bad OPEN, remote AS is %d, expected %d",
+		   peer->host, remote_as, peer->as);
+      bgp_notify_send_with_data (peer, 
+				 BGP_NOTIFY_OPEN_ERR, 
+				 BGP_NOTIFY_OPEN_BAD_PEER_AS,
+				 notify_data_remote_as, 2);
+      return -1;
+    }
+
+  /* From the rfc: Upon receipt of an OPEN message, a BGP speaker MUST
+     calculate the value of the Hold Timer by using the smaller of its
+     configured Hold Time and the Hold Time received in the OPEN message.
+     The Hold Time MUST be either zero or at least three seconds.  An
+     implementation may reject connections on the basis of the Hold Time. */
+
+  if (holdtime < 3 && holdtime != 0)
+    {
+      bgp_notify_send (peer,
+		       BGP_NOTIFY_OPEN_ERR, 
+		       BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
+      return -1;
+    }
+    
+  /* From the rfc: A reasonable maximum time between KEEPALIVE messages
+     would be one third of the Hold Time interval.  KEEPALIVE messages
+     MUST NOT be sent more frequently than one per second.  An
+     implementation MAY adjust the rate at which it sends KEEPALIVE
+     messages as a function of the Hold Time interval. */
+
+  if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
+    send_holdtime = peer->holdtime;
+  else
+    send_holdtime = peer->bgp->default_holdtime;
+
+  if (holdtime < send_holdtime)
+    peer->v_holdtime = holdtime;
+  else
+    peer->v_holdtime = send_holdtime;
+
+  peer->v_keepalive = peer->v_holdtime / 3;
+
+  /* Open option part parse. */
+  capability = 0;
+  optlen = stream_getc (peer->ibuf);
+  if (optlen != 0) 
+    {
+      ret = bgp_open_option_parse (peer, optlen, &capability);
+      if (ret < 0)
+	return ret;
+
+      stream_forward (peer->ibuf, optlen);
+    }
+  else
+    {
+      if (BGP_DEBUG (normal, NORMAL))
+	zlog_info ("%s rcvd OPEN w/ OPTION parameter len: 0",
+		   peer->host);
+    }
+
+  /* Override capability. */
+  if (! capability || CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
+    {
+      peer->afc_nego[AFI_IP][SAFI_UNICAST] = peer->afc[AFI_IP][SAFI_UNICAST];
+      peer->afc_nego[AFI_IP][SAFI_MULTICAST] = peer->afc[AFI_IP][SAFI_MULTICAST];
+      peer->afc_nego[AFI_IP6][SAFI_UNICAST] = peer->afc[AFI_IP6][SAFI_UNICAST];
+      peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = peer->afc[AFI_IP6][SAFI_MULTICAST];
+    }
+
+  /* Get sockname. */
+  bgp_getsockname (peer);
+
+  BGP_EVENT_ADD (peer, Receive_OPEN_message);
+
+  peer->packet_size = 0;
+  if (peer->ibuf)
+    stream_reset (peer->ibuf);
+
+  return 0;
+}
+
+/* Parse BGP Update packet and make attribute object. */
+int
+bgp_update_receive (struct peer *peer, bgp_size_t size)
+{
+  int ret;
+  u_char *end;
+  struct stream *s;
+  struct attr attr;
+  bgp_size_t attribute_len;
+  bgp_size_t update_len;
+  bgp_size_t withdraw_len;
+  struct bgp_nlri update;
+  struct bgp_nlri withdraw;
+  struct bgp_nlri mp_update;
+  struct bgp_nlri mp_withdraw;
+  char attrstr[BUFSIZ];
+
+  /* Status must be Established. */
+  if (peer->status != Established) 
+    {
+      zlog_err ("%s [FSM] Update packet received under status %s",
+		peer->host, LOOKUP (bgp_status_msg, peer->status));
+      bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
+      return -1;
+    }
+
+  /* Set initial values. */
+  memset (&attr, 0, sizeof (struct attr));
+  memset (&update, 0, sizeof (struct bgp_nlri));
+  memset (&withdraw, 0, sizeof (struct bgp_nlri));
+  memset (&mp_update, 0, sizeof (struct bgp_nlri));
+  memset (&mp_withdraw, 0, sizeof (struct bgp_nlri));
+
+  s = peer->ibuf;
+  end = stream_pnt (s) + size;
+
+  /* RFC1771 6.3 If the Unfeasible Routes Length or Total Attribute
+     Length is too large (i.e., if Unfeasible Routes Length + Total
+     Attribute Length + 23 exceeds the message Length), then the Error
+     Subcode is set to Malformed Attribute List.  */
+  if (stream_pnt (s) + 2 > end)
+    {
+      zlog_err ("%s [Error] Update packet error"
+		" (packet length is short for unfeasible length)",
+		peer->host);
+      bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, 
+		       BGP_NOTIFY_UPDATE_MAL_ATTR);
+      return -1;
+    }
+
+  /* Unfeasible Route Length. */
+  withdraw_len = stream_getw (s);
+
+  /* Unfeasible Route Length check. */
+  if (stream_pnt (s) + withdraw_len > end)
+    {
+      zlog_err ("%s [Error] Update packet error"
+		" (packet unfeasible length overflow %d)",
+		peer->host, withdraw_len);
+      bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, 
+		       BGP_NOTIFY_UPDATE_MAL_ATTR);
+      return -1;
+    }
+
+  /* Unfeasible Route packet format check. */
+  if (withdraw_len > 0)
+    {
+      ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), withdraw_len);
+      if (ret < 0)
+	return -1;
+
+      if (BGP_DEBUG (packet, PACKET_RECV))
+	  zlog_info ("%s [Update:RECV] Unfeasible NLRI received", peer->host);
+
+      withdraw.afi = AFI_IP;
+      withdraw.safi = SAFI_UNICAST;
+      withdraw.nlri = stream_pnt (s);
+      withdraw.length = withdraw_len;
+      stream_forward (s, withdraw_len);
+    }
+  
+  /* Attribute total length check. */
+  if (stream_pnt (s) + 2 > end)
+    {
+      zlog_warn ("%s [Error] Packet Error"
+		 " (update packet is short for attribute length)",
+		 peer->host);
+      bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, 
+		       BGP_NOTIFY_UPDATE_MAL_ATTR);
+      return -1;
+    }
+
+  /* Fetch attribute total length. */
+  attribute_len = stream_getw (s);
+
+  /* Attribute length check. */
+  if (stream_pnt (s) + attribute_len > end)
+    {
+      zlog_warn ("%s [Error] Packet Error"
+		 " (update packet attribute length overflow %d)",
+		 peer->host, attribute_len);
+      bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, 
+		       BGP_NOTIFY_UPDATE_MAL_ATTR);
+      return -1;
+    }
+
+  /* Parse attribute when it exists. */
+  if (attribute_len)
+    {
+      ret = bgp_attr_parse (peer, &attr, attribute_len, 
+			    &mp_update, &mp_withdraw);
+      if (ret < 0)
+	return -1;
+    }
+
+  /* Logging the attribute. */
+  if (BGP_DEBUG (update, UPDATE_IN))
+    {
+      bgp_dump_attr (peer, &attr, attrstr, BUFSIZ);
+      zlog (peer->log, LOG_INFO, "%s rcvd UPDATE w/ attr: %s",
+	    peer->host, attrstr);
+    }
+
+  /* Network Layer Reachability Information. */
+  update_len = end - stream_pnt (s);
+
+  if (update_len)
+    {
+      /* Check NLRI packet format and prefix length. */
+      ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), update_len);
+      if (ret < 0)
+	return -1;
+
+      /* Set NLRI portion to structure. */
+      update.afi = AFI_IP;
+      update.safi = SAFI_UNICAST;
+      update.nlri = stream_pnt (s);
+      update.length = update_len;
+      stream_forward (s, update_len);
+    }
+
+  /* NLRI is processed only when the peer is configured specific
+     Address Family and Subsequent Address Family. */
+  if (peer->afc[AFI_IP][SAFI_UNICAST])
+    {
+      if (withdraw.length)
+	bgp_nlri_parse (peer, NULL, &withdraw);
+
+      if (update.length)
+	{
+	  /* We check well-known attribute only for IPv4 unicast
+	     update. */
+	  ret = bgp_attr_check (peer, &attr);
+	  if (ret < 0)
+	    return -1;
+
+	  bgp_nlri_parse (peer, &attr, &update);
+	}
+    }
+  if (peer->afc[AFI_IP][SAFI_MULTICAST])
+    {
+      if (mp_update.length
+	  && mp_update.afi == AFI_IP 
+	  && mp_update.safi == SAFI_MULTICAST)
+	bgp_nlri_parse (peer, &attr, &mp_update);
+
+      if (mp_withdraw.length
+	  && mp_withdraw.afi == AFI_IP 
+	  && mp_withdraw.safi == SAFI_MULTICAST)
+	bgp_nlri_parse (peer, NULL, &mp_withdraw);
+    }
+  if (peer->afc[AFI_IP6][SAFI_UNICAST])
+    {
+      if (mp_update.length 
+	  && mp_update.afi == AFI_IP6 
+	  && mp_update.safi == SAFI_UNICAST)
+	bgp_nlri_parse (peer, &attr, &mp_update);
+
+      if (mp_withdraw.length 
+	  && mp_withdraw.afi == AFI_IP6 
+	  && mp_withdraw.safi == SAFI_UNICAST)
+	bgp_nlri_parse (peer, NULL, &mp_withdraw);
+    }
+  if (peer->afc[AFI_IP6][SAFI_MULTICAST])
+    {
+      if (mp_update.length 
+	  && mp_update.afi == AFI_IP6 
+	  && mp_update.safi == SAFI_MULTICAST)
+	bgp_nlri_parse (peer, &attr, &mp_update);
+
+      if (mp_withdraw.length 
+	  && mp_withdraw.afi == AFI_IP6 
+	  && mp_withdraw.safi == SAFI_MULTICAST)
+	bgp_nlri_parse (peer, NULL, &mp_withdraw);
+    }
+  if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
+    {
+      if (mp_update.length 
+	  && mp_update.afi == AFI_IP 
+	  && mp_update.safi == BGP_SAFI_VPNV4)
+	bgp_nlri_parse_vpnv4 (peer, &attr, &mp_update);
+
+      if (mp_withdraw.length 
+	  && mp_withdraw.afi == AFI_IP 
+	  && mp_withdraw.safi == BGP_SAFI_VPNV4)
+	bgp_nlri_parse_vpnv4 (peer, NULL, &mp_withdraw);
+    }
+
+  /* Everything is done.  We unintern temporary structures which
+     interned in bgp_attr_parse(). */
+  if (attr.aspath)
+    aspath_unintern (attr.aspath);
+  if (attr.community)
+    community_unintern (attr.community);
+  if (attr.ecommunity)
+    ecommunity_unintern (attr.ecommunity);
+  if (attr.cluster)
+    cluster_unintern (attr.cluster);
+  if (attr.transit)
+    transit_unintern (attr.transit);
+
+  /* If peering is stopped due to some reason, do not generate BGP
+     event.  */
+  if (peer->status != Established)
+    return 0;
+
+  /* Increment packet counter. */
+  peer->update_in++;
+  peer->update_time = time (NULL);
+
+  /* Generate BGP event. */
+  BGP_EVENT_ADD (peer, Receive_UPDATE_message);
+
+  return 0;
+}
+
+/* Notify message treatment function. */
+void
+bgp_notify_receive (struct peer *peer, bgp_size_t size)
+{
+  struct bgp_notify bgp_notify;
+
+  if (peer->notify.data)
+    {
+      XFREE (MTYPE_TMP, peer->notify.data);
+      peer->notify.data = NULL;
+      peer->notify.length = 0;
+    }
+
+  bgp_notify.code = stream_getc (peer->ibuf);
+  bgp_notify.subcode = stream_getc (peer->ibuf);
+  bgp_notify.length = size - 2;
+  bgp_notify.data = NULL;
+
+  /* Preserv notify code and sub code. */
+  peer->notify.code = bgp_notify.code;
+  peer->notify.subcode = bgp_notify.subcode;
+  /* For further diagnostic record returned Data. */
+  if (bgp_notify.length)
+    {
+      peer->notify.length = size - 2;
+      peer->notify.data = XMALLOC (MTYPE_TMP, size - 2);
+      memcpy (peer->notify.data, stream_pnt (peer->ibuf), size - 2);
+    }
+
+  /* For debug */
+  {
+    int i;
+    int first = 0;
+    char c[4];
+
+    if (bgp_notify.length)
+      {
+	bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
+	for (i = 0; i < bgp_notify.length; i++)
+	  if (first)
+	    {
+	      sprintf (c, " %02x", stream_getc (peer->ibuf));
+	      strcat (bgp_notify.data, c);
+	    }
+	  else
+	    {
+	      first = 1;
+	      sprintf (c, "%02x", stream_getc (peer->ibuf));
+	      strcpy (bgp_notify.data, c);
+	    }
+      }
+
+    bgp_notify_print(peer, &bgp_notify, "received");
+    if (bgp_notify.data)
+      XFREE (MTYPE_TMP, bgp_notify.data);
+  }
+
+  /* peer count update */
+  peer->notify_in++;
+
+  /* We have to check for Notify with Unsupported Optional Parameter.
+     in that case we fallback to open without the capability option.
+     But this done in bgp_stop. We just mark it here to avoid changing
+     the fsm tables.  */
+  if (bgp_notify.code == BGP_NOTIFY_OPEN_ERR &&
+      bgp_notify.subcode == BGP_NOTIFY_OPEN_UNSUP_PARAM )
+    UNSET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
+
+  /* Also apply to Unsupported Capability until remote router support
+     capability. */
+  if (bgp_notify.code == BGP_NOTIFY_OPEN_ERR &&
+      bgp_notify.subcode == BGP_NOTIFY_OPEN_UNSUP_CAPBL)
+    UNSET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
+
+  BGP_EVENT_ADD (peer, Receive_NOTIFICATION_message);
+}
+
+/* Keepalive treatment function -- get keepalive send keepalive */
+void
+bgp_keepalive_receive (struct peer *peer, bgp_size_t size)
+{
+  if (BGP_DEBUG (keepalive, KEEPALIVE))  
+    zlog_info ("%s KEEPALIVE rcvd", peer->host); 
+  
+  BGP_EVENT_ADD (peer, Receive_KEEPALIVE_message);
+}
+
+/* Route refresh message is received. */
+void
+bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
+{
+  afi_t afi;
+  safi_t safi;
+  u_char reserved;
+  struct stream *s;
+
+  /* If peer does not have the capability, send notification. */
+  if (! CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_ADV))
+    {
+      plog_err (peer->log, "%s [Error] BGP route refresh is not enabled",
+		peer->host);
+      bgp_notify_send (peer,
+		       BGP_NOTIFY_HEADER_ERR,
+		       BGP_NOTIFY_HEADER_BAD_MESTYPE);
+      return;
+    }
+
+  /* Status must be Established. */
+  if (peer->status != Established) 
+    {
+      plog_err (peer->log,
+		"%s [Error] Route refresh packet received under status %s",
+		peer->host, LOOKUP (bgp_status_msg, peer->status));
+      bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
+      return;
+    }
+
+  s = peer->ibuf;
+  
+  /* Parse packet. */
+  afi = stream_getw (s);
+  reserved = stream_getc (s);
+  safi = stream_getc (s);
+
+  if (BGP_DEBUG (normal, NORMAL))
+    zlog_info ("%s rcvd REFRESH_REQ for afi/safi: %d/%d",
+	       peer->host, afi, safi);
+
+  /* Check AFI and SAFI. */
+  if ((afi != AFI_IP && afi != AFI_IP6)
+      || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
+	  && safi != BGP_SAFI_VPNV4))
+    {
+      if (BGP_DEBUG (normal, NORMAL))
+	{
+	  zlog_info ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored",
+		     peer->host, afi, safi);
+	}
+      return;
+    }
+
+  /* Adjust safi code. */
+  if (safi == BGP_SAFI_VPNV4)
+    safi = SAFI_MPLS_VPN;
+
+  if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE)
+    {
+      u_char *end;
+      u_char when_to_refresh;
+      u_char orf_type;
+      u_int16_t orf_len;
+
+      if (size - (BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) < 5)
+        {
+          zlog_info ("%s ORF route refresh length error", peer->host);
+          bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+          return;
+        }
+
+      when_to_refresh = stream_getc (s);
+      end = stream_pnt (s) + (size - 5);
+
+      while (stream_pnt (s) < end)
+	{
+	  orf_type = stream_getc (s); 
+	  orf_len = stream_getw (s);
+
+	  if (orf_type == ORF_TYPE_PREFIX
+	      || orf_type == ORF_TYPE_PREFIX_OLD)
+	    {
+	      u_char *p_pnt = stream_pnt (s);
+	      u_char *p_end = stream_pnt (s) + orf_len;
+	      struct orf_prefix orfp;
+	      u_char common = 0;
+	      u_int32_t seq;
+	      int psize;
+	      char name[BUFSIZ];
+	      char buf[BUFSIZ];
+	      int ret;
+
+	      if (BGP_DEBUG (normal, NORMAL))
+		{
+		  zlog_info ("%s rcvd Prefixlist ORF(%d) length %d",
+			     peer->host, orf_type, orf_len);
+		}
+
+	      /* ORF prefix-list name */
+	      sprintf (name, "%s.%d.%d", peer->host, afi, safi);
+
+	      while (p_pnt < p_end)
+		{
+		  memset (&orfp, 0, sizeof (struct orf_prefix));
+		  common = *p_pnt++;
+		  if (common & ORF_COMMON_PART_REMOVE_ALL)
+		    {
+		      if (BGP_DEBUG (normal, NORMAL))
+			zlog_info ("%s rcvd Remove-All pfxlist ORF request", peer->host);
+		      prefix_bgp_orf_remove_all (name);
+		      break;
+		    }
+		  memcpy (&seq, p_pnt, sizeof (u_int32_t));
+		  p_pnt += sizeof (u_int32_t);
+		  orfp.seq = ntohl (seq);
+		  orfp.ge = *p_pnt++;
+		  orfp.le = *p_pnt++;
+		  orfp.p.prefixlen = *p_pnt++;
+		  orfp.p.family = afi2family (afi);
+		  psize = PSIZE (orfp.p.prefixlen);
+		  memcpy (&orfp.p.u.prefix, p_pnt, psize);
+		  p_pnt += psize;
+
+		  if (BGP_DEBUG (normal, NORMAL))
+		    zlog_info ("%s rcvd %s %s seq %u %s/%d ge %d le %d",
+			       peer->host,
+			       (common & ORF_COMMON_PART_REMOVE ? "Remove" : "Add"), 
+			       (common & ORF_COMMON_PART_DENY ? "deny" : "permit"),
+			       orfp.seq, 
+			       inet_ntop (orfp.p.family, &orfp.p.u.prefix, buf, BUFSIZ),
+			       orfp.p.prefixlen, orfp.ge, orfp.le);
+
+		  ret = prefix_bgp_orf_set (name, afi, &orfp,
+				 (common & ORF_COMMON_PART_DENY ? 0 : 1 ),
+				 (common & ORF_COMMON_PART_REMOVE ? 0 : 1));
+
+		  if (ret != CMD_SUCCESS)
+		    {
+		      if (BGP_DEBUG (normal, NORMAL))
+			zlog_info ("%s Received misformatted prefixlist ORF. Remove All pfxlist", peer->host);
+		      prefix_bgp_orf_remove_all (name);
+		      break;
+		    }
+		}
+	      peer->orf_plist[afi][safi] =
+			 prefix_list_lookup (AFI_ORF_PREFIX, name);
+	    }
+	  stream_forward (s, orf_len);
+	}
+      if (BGP_DEBUG (normal, NORMAL))
+	zlog_info ("%s rcvd Refresh %s ORF request", peer->host,
+		   when_to_refresh == REFRESH_DEFER ? "Defer" : "Immediate");
+      if (when_to_refresh == REFRESH_DEFER)
+	return;
+    }
+
+  /* First update is deferred until ORF or ROUTE-REFRESH is received */
+  if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH))
+    UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
+
+  /* Perform route refreshment to the peer */
+  bgp_announce_route (peer, afi, safi);
+}
+
+int
+bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
+{
+  u_char *end;
+  struct capability cap;
+  u_char action;
+  struct bgp *bgp;
+  afi_t afi;
+  safi_t safi;
+
+  bgp = peer->bgp;
+  end = pnt + length;
+
+  while (pnt < end)
+    {
+      /* We need at least action, capability code and capability length. */
+      if (pnt + 3 > end)
+        {
+          zlog_info ("%s Capability length error", peer->host);
+          bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+          return -1;
+        }
+
+      action = *pnt;
+
+      /* Fetch structure to the byte stream. */
+      memcpy (&cap, pnt + 1, sizeof (struct capability));
+
+      /* Action value check.  */
+      if (action != CAPABILITY_ACTION_SET
+	  && action != CAPABILITY_ACTION_UNSET)
+        {
+          zlog_info ("%s Capability Action Value error %d",
+		     peer->host, action);
+          bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+          return -1;
+        }
+
+      if (BGP_DEBUG (normal, NORMAL))
+	zlog_info ("%s CAPABILITY has action: %d, code: %u, length %u",
+		   peer->host, action, cap.code, cap.length);
+
+      /* Capability length check. */
+      if (pnt + (cap.length + 3) > end)
+        {
+          zlog_info ("%s Capability length error", peer->host);
+          bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+          return -1;
+        }
+
+      /* We know MP Capability Code. */
+      if (cap.code == CAPABILITY_CODE_MP)
+        {
+	  afi = ntohs (cap.mpc.afi);
+	  safi = cap.mpc.safi;
+
+          /* Ignore capability when override-capability is set. */
+          if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
+	    continue;
+
+	  /* Address family check.  */
+	  if ((afi == AFI_IP 
+	       || afi == AFI_IP6)
+	      && (safi == SAFI_UNICAST 
+		  || safi == SAFI_MULTICAST 
+		  || safi == BGP_SAFI_VPNV4))
+	    {
+	      if (BGP_DEBUG (normal, NORMAL))
+		zlog_info ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u",
+			   peer->host,
+			   action == CAPABILITY_ACTION_SET 
+			   ? "Advertising" : "Removing",
+			   ntohs(cap.mpc.afi) , cap.mpc.safi);
+		  
+	      /* Adjust safi code. */
+	      if (safi == BGP_SAFI_VPNV4)
+		safi = SAFI_MPLS_VPN;
+	      
+	      if (action == CAPABILITY_ACTION_SET)
+		{
+		  peer->afc_recv[afi][safi] = 1;
+		  if (peer->afc[afi][safi])
+		    {
+		      peer->afc_nego[afi][safi] = 1;
+		      bgp_announce_route (peer, afi, safi);
+		    }
+		}
+	      else
+		{
+		  peer->afc_recv[afi][safi] = 0;
+		  peer->afc_nego[afi][safi] = 0;
+
+		  if (peer_active_nego (peer))
+		    bgp_clear_route (peer, afi, safi);
+		  else
+		    BGP_EVENT_ADD (peer, BGP_Stop);
+		} 
+	    }
+        }
+      else if (cap.code == CAPABILITY_CODE_REFRESH
+	       || cap.code == CAPABILITY_CODE_REFRESH_OLD)
+        {
+          /* Check length. */
+          if (cap.length != 0)
+            {
+              zlog_info ("%s Route Refresh Capability length error %d",
+                         peer->host, cap.length);
+              bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+              return -1;
+            }
+	  
+          if (BGP_DEBUG (normal, NORMAL))
+            zlog_info ("%s CAPABILITY has %s ROUTE-REFRESH capability(%s) for all address-families",
+		       peer->host,
+		       action == CAPABILITY_ACTION_SET
+		       ? "Advertising" : "Removing",
+		       cap.code == CAPABILITY_CODE_REFRESH_OLD
+		       ? "old" : "new");
+	  
+          /* BGP refresh capability */
+	  if (action == CAPABILITY_ACTION_SET)
+	    {
+	      if (cap.code == CAPABILITY_CODE_REFRESH_OLD)
+		SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
+	      else
+		SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
+	    }
+	  else
+	    {
+	      if (cap.code == CAPABILITY_CODE_REFRESH_OLD)
+		UNSET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
+	      else
+		UNSET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
+	    }
+        }
+      else
+        {
+          zlog_warn ("%s unrecognized capability code: %d - ignored",
+                     peer->host, cap.code);
+        }
+      pnt += cap.length + 3;
+    }
+  return 0;
+}
+
+/* Dynamic Capability is received. */
+void
+bgp_capability_receive (struct peer *peer, bgp_size_t size)
+{
+  u_char *pnt;
+  int ret;
+
+  /* Fetch pointer. */
+  pnt = stream_pnt (peer->ibuf);
+
+  if (BGP_DEBUG (normal, NORMAL))
+    zlog_info ("%s rcv CAPABILITY", peer->host);
+
+  /* If peer does not have the capability, send notification. */
+  if (! CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV))
+    {
+      plog_err (peer->log, "%s [Error] BGP dynamic capability is not enabled",
+		peer->host);
+      bgp_notify_send (peer,
+		       BGP_NOTIFY_HEADER_ERR,
+		       BGP_NOTIFY_HEADER_BAD_MESTYPE);
+      return;
+    }
+
+  /* Status must be Established. */
+  if (peer->status != Established)
+    {
+      plog_err (peer->log,
+		"%s [Error] Dynamic capability packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status));
+      bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
+      return;
+    }
+
+  /* Parse packet. */
+  ret = bgp_capability_msg_parse (peer, pnt, size);
+}
+
+/* BGP read utility function. */
+int
+bgp_read_packet (struct peer *peer)
+{
+  int nbytes;
+  int readsize;
+
+  readsize = peer->packet_size - peer->ibuf->putp;
+
+  /* If size is zero then return. */
+  if (! readsize)
+    return 0;
+
+  /* Read packet from fd. */
+  nbytes = stream_read_unblock (peer->ibuf, peer->fd, readsize);
+
+  /* If read byte is smaller than zero then error occured. */
+  if (nbytes < 0) 
+    {
+      if (errno == EAGAIN)
+	return -1;
+
+      plog_err (peer->log, "%s [Error] bgp_read_packet error: %s",
+		 peer->host, strerror (errno));
+      BGP_EVENT_ADD (peer, TCP_fatal_error);
+      return -1;
+    }  
+
+  /* When read byte is zero : clear bgp peer and return */
+  if (nbytes == 0) 
+    {
+      if (BGP_DEBUG (events, EVENTS))
+	plog_info (peer->log, "%s [Event] BGP connection closed fd %d",
+		   peer->host, peer->fd);
+      BGP_EVENT_ADD (peer, TCP_connection_closed);
+      return -1;
+    }
+
+  /* We read partial packet. */
+  if (peer->ibuf->putp != peer->packet_size)
+    return -1;
+
+  return 0;
+}
+
+/* Marker check. */
+int
+bgp_marker_all_one (struct stream *s, int length)
+{
+  int i;
+
+  for (i = 0; i < length; i++)
+    if (s->data[i] != 0xff)
+      return 0;
+
+  return 1;
+}
+
+/* Starting point of packet process function. */
+int
+bgp_read (struct thread *thread)
+{
+  int ret;
+  u_char type = 0;
+  struct peer *peer;
+  bgp_size_t size;
+  char notify_data_length[2];
+
+  /* Yes first of all get peer pointer. */
+  peer = THREAD_ARG (thread);
+  peer->t_read = NULL;
+
+  /* For non-blocking IO check. */
+  if (peer->status == Connect)
+    {
+      bgp_connect_check (peer);
+      goto done;
+    }
+  else
+    {
+      if (peer->fd < 0)
+	{
+	  zlog_err ("bgp_read peer's fd is negative value %d", peer->fd);
+	  return -1;
+	}
+      BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
+    }
+
+  /* Read packet header to determine type of the packet */
+  if (peer->packet_size == 0)
+    peer->packet_size = BGP_HEADER_SIZE;
+
+  if (peer->ibuf->putp < BGP_HEADER_SIZE)
+    {
+      ret = bgp_read_packet (peer);
+
+      /* Header read error or partial read packet. */
+      if (ret < 0) 
+	goto done;
+
+      /* Get size and type. */
+      stream_forward (peer->ibuf, BGP_MARKER_SIZE);
+      memcpy (notify_data_length, stream_pnt (peer->ibuf), 2);
+      size = stream_getw (peer->ibuf);
+      type = stream_getc (peer->ibuf);
+
+      if (BGP_DEBUG (normal, NORMAL) && type != 2 && type != 0)
+	zlog_info ("%s rcv message type %d, length (excl. header) %d",
+		   peer->host, type, size - BGP_HEADER_SIZE);
+
+      /* Marker check */
+      if (type == BGP_MSG_OPEN
+	  && ! bgp_marker_all_one (peer->ibuf, BGP_MARKER_SIZE))
+	{
+	  bgp_notify_send (peer,
+			   BGP_NOTIFY_HEADER_ERR, 
+			   BGP_NOTIFY_HEADER_NOT_SYNC);
+	  goto done;
+	}
+
+      /* BGP type check. */
+      if (type != BGP_MSG_OPEN && type != BGP_MSG_UPDATE 
+	  && type != BGP_MSG_NOTIFY && type != BGP_MSG_KEEPALIVE 
+	  && type != BGP_MSG_ROUTE_REFRESH_NEW
+	  && type != BGP_MSG_ROUTE_REFRESH_OLD
+	  && type != BGP_MSG_CAPABILITY)
+	{
+	  if (BGP_DEBUG (normal, NORMAL))
+	    plog_err (peer->log,
+		      "%s unknown message type 0x%02x",
+		      peer->host, type);
+	  bgp_notify_send_with_data (peer,
+				     BGP_NOTIFY_HEADER_ERR,
+			 	     BGP_NOTIFY_HEADER_BAD_MESTYPE,
+				     &type, 1);
+	  goto done;
+	}
+      /* Mimimum packet length check. */
+      if ((size < BGP_HEADER_SIZE)
+	  || (size > BGP_MAX_PACKET_SIZE)
+	  || (type == BGP_MSG_OPEN && size < BGP_MSG_OPEN_MIN_SIZE)
+	  || (type == BGP_MSG_UPDATE && size < BGP_MSG_UPDATE_MIN_SIZE)
+	  || (type == BGP_MSG_NOTIFY && size < BGP_MSG_NOTIFY_MIN_SIZE)
+	  || (type == BGP_MSG_KEEPALIVE && size != BGP_MSG_KEEPALIVE_MIN_SIZE)
+	  || (type == BGP_MSG_ROUTE_REFRESH_NEW && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
+	  || (type == BGP_MSG_ROUTE_REFRESH_OLD && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
+	  || (type == BGP_MSG_CAPABILITY && size < BGP_MSG_CAPABILITY_MIN_SIZE))
+	{
+	  if (BGP_DEBUG (normal, NORMAL))
+	    plog_err (peer->log,
+		      "%s bad message length - %d for %s",
+		      peer->host, size, 
+		      type == 128 ? "ROUTE-REFRESH" :
+		      bgp_type_str[(int) type]);
+	  bgp_notify_send_with_data (peer,
+				     BGP_NOTIFY_HEADER_ERR,
+			  	     BGP_NOTIFY_HEADER_BAD_MESLEN,
+				     notify_data_length, 2);
+	  goto done;
+	}
+
+      /* Adjust size to message length. */
+      peer->packet_size = size;
+    }
+
+  ret = bgp_read_packet (peer);
+  if (ret < 0) 
+    goto done;
+
+  /* Get size and type again. */
+  size = stream_getw_from (peer->ibuf, BGP_MARKER_SIZE);
+  type = stream_getc_from (peer->ibuf, BGP_MARKER_SIZE + 2);
+
+  /* BGP packet dump function. */
+  bgp_dump_packet (peer, type, peer->ibuf);
+  
+  size = (peer->packet_size - BGP_HEADER_SIZE);
+
+  /* Read rest of the packet and call each sort of packet routine */
+  switch (type) 
+    {
+    case BGP_MSG_OPEN:
+      peer->open_in++;
+      bgp_open_receive (peer, size);
+      break;
+    case BGP_MSG_UPDATE:
+      peer->readtime = time(NULL);    /* Last read timer reset */
+      bgp_update_receive (peer, size);
+      break;
+    case BGP_MSG_NOTIFY:
+      bgp_notify_receive (peer, size);
+      break;
+    case BGP_MSG_KEEPALIVE:
+      peer->readtime = time(NULL);    /* Last read timer reset */
+      bgp_keepalive_receive (peer, size);
+      break;
+    case BGP_MSG_ROUTE_REFRESH_NEW:
+    case BGP_MSG_ROUTE_REFRESH_OLD:
+      peer->refresh_in++;
+      bgp_route_refresh_receive (peer, size);
+      break;
+    case BGP_MSG_CAPABILITY:
+      peer->dynamic_cap_in++;
+      bgp_capability_receive (peer, size);
+      break;
+    }
+
+  /* Clear input buffer. */
+  peer->packet_size = 0;
+  if (peer->ibuf)
+    stream_reset (peer->ibuf);
+
+ done:
+  if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
+    {
+      if (BGP_DEBUG (events, EVENTS))
+	zlog_info ("%s [Event] Accepting BGP peer delete", peer->host);
+      peer_delete (peer);
+    }
+  return 0;
+}
diff --git a/bgpd/bgp_packet.h b/bgpd/bgp_packet.h
new file mode 100644
index 0000000..c1efc8b
--- /dev/null
+++ b/bgpd/bgp_packet.h
@@ -0,0 +1,49 @@
+/* BGP packet management header.
+   Copyright (C) 1999 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#define BGP_NLRI_LENGTH       1
+#define BGP_TOTAL_ATTR_LEN    2
+#define BGP_UNFEASIBLE_LEN    2
+#define BGP_WRITE_PACKET_MAX 10
+
+/* When to refresh */
+#define REFRESH_IMMEDIATE 1
+#define REFRESH_DEFER     2 
+
+/* ORF Common part flag */
+#define ORF_COMMON_PART_ADD        0x00 
+#define ORF_COMMON_PART_REMOVE     0x80 
+#define ORF_COMMON_PART_REMOVE_ALL 0xC0 
+#define ORF_COMMON_PART_PERMIT     0x00 
+#define ORF_COMMON_PART_DENY       0x20 
+
+/* Packet send and receive function prototypes. */
+int bgp_read (struct thread *);
+int bgp_write (struct thread *);
+
+void bgp_keepalive_send (struct peer *);
+void bgp_open_send (struct peer *);
+void bgp_notify_send (struct peer *, u_char, u_char);
+void bgp_notify_send_with_data (struct peer *, u_char, u_char, u_char *, size_t);
+void bgp_route_refresh_send (struct peer *, afi_t, safi_t, u_char, u_char, int);
+void bgp_capability_send (struct peer *, afi_t, safi_t, int, int);
+void bgp_default_update_send (struct peer *, struct attr *,
+			      afi_t, safi_t, struct peer *);
+void bgp_default_withdraw_send (struct peer *, afi_t, safi_t);
diff --git a/bgpd/bgp_regex.c b/bgpd/bgp_regex.c
new file mode 100644
index 0000000..a6b6598
--- /dev/null
+++ b/bgpd/bgp_regex.c
@@ -0,0 +1,93 @@
+/* AS regular expression routine
+   Copyright (C) 1999 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "log.h"
+#include "command.h"
+#include "memory.h"
+
+#include "bgpd.h"
+#include "bgp_aspath.h"
+#include "bgp_regex.h"
+
+/* Character `_' has special mean.  It represents [,{}() ] and the
+   beginning of the line(^) and the end of the line ($).  
+
+   (^|[,{}() ]|$) */
+
+regex_t *
+bgp_regcomp (char *regstr)
+{
+  /* Convert _ character to generic regular expression. */
+  int i, j;
+  int len;
+  int magic = 0;
+  char *magic_str;
+  char magic_regexp[] = "(^|[,{}() ]|$)";
+  int ret;
+  regex_t *regex;
+
+  len = strlen (regstr);
+  for (i = 0; i < len; i++)
+    if (regstr[i] == '_')
+      magic++;
+
+  magic_str = XMALLOC (MTYPE_TMP, len + (14 * magic) + 1);
+  
+  for (i = 0, j = 0; i < len; i++)
+    {
+      if (regstr[i] == '_')
+	{
+	  memcpy (magic_str + j, magic_regexp, strlen (magic_regexp));
+	  j += strlen (magic_regexp);
+	}
+      else
+	magic_str[j++] = regstr[i];
+    }
+  magic_str[j] = '\0';
+
+  regex = XMALLOC (MTYPE_BGP_REGEXP, sizeof (regex_t));
+
+  ret = regcomp (regex, magic_str, REG_EXTENDED);
+
+  XFREE (MTYPE_TMP, magic_str);
+
+  if (ret != 0)
+    {
+      XFREE (MTYPE_BGP_REGEXP, regex);
+      return NULL;
+    }
+
+  return regex;
+}
+
+int
+bgp_regexec (regex_t *regex, struct aspath *aspath)
+{
+  return regexec (regex, aspath->str, 0, NULL, 0);
+}
+
+void
+bgp_regex_free (regex_t *regex)
+{
+  regfree (regex);
+  XFREE (MTYPE_BGP_REGEXP, regex);
+}
diff --git a/bgpd/bgp_regex.h b/bgpd/bgp_regex.h
new file mode 100644
index 0000000..0829dd9
--- /dev/null
+++ b/bgpd/bgp_regex.h
@@ -0,0 +1,31 @@
+/* AS regular expression routine
+   Copyright (C) 1999 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#ifdef HAVE_GNU_REGEX
+#include <regex.h>
+#else
+#include "regex-gnu.h"
+#endif /* HAVE_GNU_REGEX */
+
+void bgp_regex_free (regex_t *regex);
+regex_t *bgp_regcomp (char *str);
+int bgp_regexec (regex_t *regex, struct aspath *aspath);
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
new file mode 100644
index 0000000..87d305c
--- /dev/null
+++ b/bgpd/bgp_route.c
@@ -0,0 +1,9053 @@
+/* BGP routing information
+   Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "prefix.h"
+#include "linklist.h"
+#include "memory.h"
+#include "command.h"
+#include "stream.h"
+#include "filter.h"
+#include "str.h"
+#include "log.h"
+#include "routemap.h"
+#include "buffer.h"
+#include "sockunion.h"
+#include "plist.h"
+#include "thread.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_table.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_aspath.h"
+#include "bgpd/bgp_regex.h"
+#include "bgpd/bgp_community.h"
+#include "bgpd/bgp_ecommunity.h"
+#include "bgpd/bgp_clist.h"
+#include "bgpd/bgp_packet.h"
+#include "bgpd/bgp_filter.h"
+#include "bgpd/bgp_fsm.h"
+#include "bgpd/bgp_mplsvpn.h"
+#include "bgpd/bgp_nexthop.h"
+#include "bgpd/bgp_damp.h"
+#include "bgpd/bgp_advertise.h"
+#include "bgpd/bgp_zebra.h"
+
+/* Extern from bgp_dump.c */
+extern char *bgp_origin_str[];
+extern char *bgp_origin_long_str[];
+
+struct bgp_node *
+bgp_afi_node_get (struct bgp *bgp, afi_t afi, safi_t safi, struct prefix *p,
+		  struct prefix_rd *prd)
+{
+  struct bgp_node *rn;
+  struct bgp_node *prn = NULL;
+  struct bgp_table *table;
+
+  if (safi == SAFI_MPLS_VPN)
+    {
+      prn = bgp_node_get (bgp->rib[afi][safi], (struct prefix *) prd);
+
+      if (prn->info == NULL)
+	prn->info = bgp_table_init ();
+      else
+	bgp_unlock_node (prn);
+      table = prn->info;
+    }
+  else
+    table = bgp->rib[afi][safi];
+
+  rn = bgp_node_get (table, p);
+
+  if (safi == SAFI_MPLS_VPN)
+    rn->prn = prn;
+
+  return rn;
+}
+
+/* Allocate new bgp info structure. */
+struct bgp_info *
+bgp_info_new ()
+{
+  struct bgp_info *new;
+
+  new = XMALLOC (MTYPE_BGP_ROUTE, sizeof (struct bgp_info));
+  memset (new, 0, sizeof (struct bgp_info));
+
+  return new;
+}
+
+/* Free bgp route information. */
+void
+bgp_info_free (struct bgp_info *binfo)
+{
+  if (binfo->attr)
+    bgp_attr_unintern (binfo->attr);
+
+  if (binfo->damp_info)
+    bgp_damp_info_free (binfo->damp_info, 0);
+
+  XFREE (MTYPE_BGP_ROUTE, binfo);
+}
+
+void
+bgp_info_add (struct bgp_node *rn, struct bgp_info *ri)
+{
+  struct bgp_info *top;
+
+  top = rn->info;
+
+  ri->next = rn->info;
+  ri->prev = NULL;
+  if (top)
+    top->prev = ri;
+  rn->info = ri;
+}
+
+void
+bgp_info_delete (struct bgp_node *rn, struct bgp_info *ri)
+{
+  if (ri->next)
+    ri->next->prev = ri->prev;
+  if (ri->prev)
+    ri->prev->next = ri->next;
+  else
+    rn->info = ri->next;
+}
+
+/* Get MED value.  If MED value is missing and "bgp bestpath
+   missing-as-worst" is specified, treat it as the worst value. */
+u_int32_t
+bgp_med_value (struct attr *attr, struct bgp *bgp)
+{
+  if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
+    return attr->med;
+  else
+    {
+      if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
+	return 4294967295ul;
+      else
+	return 0;
+    }
+}
+
+/* Compare two bgp route entity.  br is preferable then return 1. */
+int
+bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist)
+{
+  u_int32_t new_pref;
+  u_int32_t exist_pref;
+  u_int32_t new_med;
+  u_int32_t exist_med;
+  struct in_addr new_id;
+  struct in_addr exist_id;
+  int new_cluster;
+  int exist_cluster;
+  int internal_as_route = 0;
+  int confed_as_route = 0;
+  int ret;
+
+  /* 0. Null check. */
+  if (new == NULL)
+    return 0;
+  if (exist == NULL)
+    return 1;
+
+  /* 1. Weight check. */
+  if (new->attr->weight > exist->attr->weight)
+    return 1;
+  if (new->attr->weight < exist->attr->weight)
+    return 0;
+
+  /* 2. Local preference check. */
+  if (new->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
+    new_pref = new->attr->local_pref;
+  else
+    new_pref = bgp->default_local_pref;
+
+  if (exist->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
+    exist_pref = exist->attr->local_pref;
+  else
+    exist_pref = bgp->default_local_pref;
+    
+  if (new_pref > exist_pref)
+    return 1;
+  if (new_pref < exist_pref)
+    return 0;
+
+  /* 3. Local route check. */
+  if (new->sub_type == BGP_ROUTE_STATIC)
+    return 1;
+  if (exist->sub_type == BGP_ROUTE_STATIC)
+    return 0;
+
+  if (new->sub_type == BGP_ROUTE_REDISTRIBUTE)
+    return 1;
+  if (exist->sub_type == BGP_ROUTE_REDISTRIBUTE)
+    return 0;
+
+  if (new->sub_type == BGP_ROUTE_AGGREGATE)
+    return 1;
+  if (exist->sub_type == BGP_ROUTE_AGGREGATE)
+    return 0;
+
+  /* 4. AS path length check. */
+  if (! bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
+    {
+      if (new->attr->aspath->count < exist->attr->aspath->count)
+	return 1;
+      if (new->attr->aspath->count > exist->attr->aspath->count)
+	return 0;
+    }
+
+  /* 5. Origin check. */
+  if (new->attr->origin < exist->attr->origin)
+    return 1;
+  if (new->attr->origin > exist->attr->origin)
+    return 0;
+
+  /* 6. MED check. */
+  internal_as_route = (new->attr->aspath->length == 0
+		      && exist->attr->aspath->length == 0);
+  confed_as_route = (new->attr->aspath->length > 0
+		    && exist->attr->aspath->length > 0
+		    && new->attr->aspath->count == 0
+		    && exist->attr->aspath->count == 0);
+  
+  if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED)
+      || (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
+	 && confed_as_route)
+      || aspath_cmp_left (new->attr->aspath, exist->attr->aspath)
+      || aspath_cmp_left_confed (new->attr->aspath, exist->attr->aspath)
+      || internal_as_route)
+    {
+      new_med = bgp_med_value (new->attr, bgp);
+      exist_med = bgp_med_value (exist->attr, bgp);
+
+      if (new_med < exist_med)
+	return 1;
+      if (new_med > exist_med)
+	return 0;
+    }
+
+  /* 7. Peer type check. */
+  if (peer_sort (new->peer) == BGP_PEER_EBGP 
+      && peer_sort (exist->peer) == BGP_PEER_IBGP)
+    return 1;
+  if (peer_sort (new->peer) == BGP_PEER_EBGP 
+      && peer_sort (exist->peer) == BGP_PEER_CONFED)
+    return 1;
+  if (peer_sort (new->peer) == BGP_PEER_IBGP 
+      && peer_sort (exist->peer) == BGP_PEER_EBGP)
+    return 0;
+  if (peer_sort (new->peer) == BGP_PEER_CONFED 
+      && peer_sort (exist->peer) == BGP_PEER_EBGP)
+    return 0;
+
+  /* 8. IGP metric check. */
+  if (new->igpmetric < exist->igpmetric)
+    return 1;
+  if (new->igpmetric > exist->igpmetric)
+    return 0;
+
+  /* 9. Maximum path check. */
+
+  /* 10. If both paths are external, prefer the path that was received
+     first (the oldest one).  This step minimizes route-flap, since a
+     newer path won't displace an older one, even if it was the
+     preferred route based on the additional decision criteria below.  */
+  if (! bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID)
+      && peer_sort (new->peer) == BGP_PEER_EBGP
+      && peer_sort (exist->peer) == BGP_PEER_EBGP)
+    {
+      if (CHECK_FLAG (new->flags, BGP_INFO_SELECTED))
+	return 1;
+      if (CHECK_FLAG (exist->flags, BGP_INFO_SELECTED))
+	return 0;
+    }
+
+  /* 11. Rourter-ID comparision. */
+  if (new->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
+    new_id.s_addr = new->attr->originator_id.s_addr;
+  else
+    new_id.s_addr = new->peer->remote_id.s_addr;
+  if (exist->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
+    exist_id.s_addr = exist->attr->originator_id.s_addr;
+  else
+    exist_id.s_addr = exist->peer->remote_id.s_addr;
+
+  if (ntohl (new_id.s_addr) < ntohl (exist_id.s_addr))
+    return 1;
+  if (ntohl (new_id.s_addr) > ntohl (exist_id.s_addr))
+    return 0;
+
+  /* 12. Cluster length comparision. */
+  if (new->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))
+    new_cluster = new->attr->cluster->length;
+  else
+    new_cluster = 0;
+  if (exist->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))
+    exist_cluster = exist->attr->cluster->length;
+  else
+    exist_cluster = 0;
+
+  if (new_cluster < exist_cluster)
+    return 1;
+  if (new_cluster > exist_cluster)
+    return 0;
+
+  /* 13. Neighbor address comparision. */
+  ret = sockunion_cmp (new->peer->su_remote, exist->peer->su_remote);
+
+  if (ret == 1)
+    return 0;
+  if (ret == -1)
+    return 1;
+
+  return 1;
+}
+
+enum filter_type
+bgp_input_filter (struct peer *peer, struct prefix *p, struct attr *attr,
+		  afi_t afi, safi_t safi)
+{
+  struct bgp_filter *filter;
+
+  filter = &peer->filter[afi][safi];
+
+  if (DISTRIBUTE_IN_NAME (filter))
+    if (access_list_apply (DISTRIBUTE_IN (filter), p) == FILTER_DENY)
+      return FILTER_DENY;
+
+  if (PREFIX_LIST_IN_NAME (filter))
+    if (prefix_list_apply (PREFIX_LIST_IN (filter), p) == PREFIX_DENY)
+      return FILTER_DENY;
+  
+  if (FILTER_LIST_IN_NAME (filter))
+    if (as_list_apply (FILTER_LIST_IN (filter), attr->aspath)== AS_FILTER_DENY)
+      return FILTER_DENY;
+
+  return FILTER_PERMIT;
+}
+
+enum filter_type
+bgp_output_filter (struct peer *peer, struct prefix *p, struct attr *attr,
+		   afi_t afi, safi_t safi)
+{
+  struct bgp_filter *filter;
+
+  filter = &peer->filter[afi][safi];
+
+  if (DISTRIBUTE_OUT_NAME (filter))
+    if (access_list_apply (DISTRIBUTE_OUT (filter), p) == FILTER_DENY)
+      return FILTER_DENY;
+
+  if (PREFIX_LIST_OUT_NAME (filter))
+    if (prefix_list_apply (PREFIX_LIST_OUT (filter), p) == PREFIX_DENY)
+      return FILTER_DENY;
+
+  if (FILTER_LIST_OUT_NAME (filter))
+    if (as_list_apply (FILTER_LIST_OUT (filter), attr->aspath) == AS_FILTER_DENY)
+      return FILTER_DENY;
+
+  return FILTER_PERMIT;
+}
+
+/* If community attribute includes no_export then return 1. */
+int
+bgp_community_filter (struct peer *peer, struct attr *attr)
+{
+  if (attr->community)
+    {
+      /* NO_ADVERTISE check. */
+      if (community_include (attr->community, COMMUNITY_NO_ADVERTISE))
+	return 1;
+
+      /* NO_EXPORT check. */
+      if (peer_sort (peer) == BGP_PEER_EBGP &&
+	  community_include (attr->community, COMMUNITY_NO_EXPORT))
+	return 1;
+
+      /* NO_EXPORT_SUBCONFED check. */
+      if (peer_sort (peer) == BGP_PEER_EBGP 
+	  || peer_sort (peer) == BGP_PEER_CONFED)
+	if (community_include (attr->community, COMMUNITY_NO_EXPORT_SUBCONFED))
+	  return 1;
+    }
+  return 0;
+}
+
+/* Route reflection loop check.  */
+static int
+bgp_cluster_filter (struct peer *peer, struct attr *attr)
+{
+  struct in_addr cluster_id;
+
+  if (attr->cluster)
+    {
+      if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
+	cluster_id = peer->bgp->cluster_id;
+      else
+	cluster_id = peer->bgp->router_id;
+      
+      if (cluster_loop_check (attr->cluster, cluster_id))
+	return 1;
+    }
+  return 0;
+}
+
+int
+bgp_input_modifier (struct peer *peer, struct prefix *p, struct attr *attr,
+		    afi_t afi, safi_t safi)
+{
+  struct bgp_filter *filter;
+  struct bgp_info info;
+  route_map_result_t ret;
+
+  filter = &peer->filter[afi][safi];
+
+  /* Apply default weight value. */
+  attr->weight = peer->weight;
+
+  /* Route map apply. */
+  if (ROUTE_MAP_IN_NAME (filter))
+    {
+      /* Duplicate current value to new strucutre for modification. */
+      info.peer = peer;
+      info.attr = attr;
+
+      /* Apply BGP route map to the attribute. */
+      ret = route_map_apply (ROUTE_MAP_IN (filter), p, RMAP_BGP, &info);
+      if (ret == RMAP_DENYMATCH)
+	{
+	  /* Free newly generated AS path and community by route-map. */
+	  bgp_attr_flush (attr);
+	  return RMAP_DENY;
+	}
+    }
+  return RMAP_PERMIT;
+}
+
+int
+bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
+		    struct attr *attr, afi_t afi, safi_t safi)
+{
+  int ret;
+  char buf[SU_ADDRSTRLEN];
+  struct bgp_filter *filter;
+  struct bgp_info info;
+  struct peer *from;
+  struct bgp *bgp;
+  struct attr dummy_attr;
+  int transparent;
+  int reflect;
+
+  from = ri->peer;
+  filter = &peer->filter[afi][safi];
+  bgp = peer->bgp;
+  
+#ifdef DISABLE_BGP_ANNOUNCE
+  return 0;
+#endif
+
+  /* Do not send back route to sender. */
+  if (from == peer)
+    return 0;
+
+  /* Aggregate-address suppress check. */
+  if (ri->suppress)
+    if (! UNSUPPRESS_MAP_NAME (filter))
+      return 0;
+
+  /* Default route check.  */
+  if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE))
+    {
+      if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
+	return 0;
+#ifdef HAVE_IPV6
+      else if (p->family == AF_INET6 && p->prefixlen == 0)
+	return 0;
+#endif /* HAVE_IPV6 */
+    }
+
+  /* If community is not disabled check the no-export and local. */
+  if (bgp_community_filter (peer, ri->attr)) 
+    return 0;
+
+  /* If the attribute has originator-id and it is same as remote
+     peer's id. */
+  if (ri->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID))
+    {
+      if (IPV4_ADDR_SAME (&peer->remote_id, &ri->attr->originator_id))
+	{
+	  if (BGP_DEBUG (filter, FILTER))  
+	    zlog (peer->log, LOG_INFO,
+		  "%s [Update:SEND] %s/%d originator-id is same as remote router-id",
+		  peer->host,
+		  inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+		  p->prefixlen);
+	  return 0;
+	}
+    }
+ 
+  /* ORF prefix-list filter check */
+  if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
+      && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
+	  || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
+    if (peer->orf_plist[afi][safi])
+      {
+	if (prefix_list_apply (peer->orf_plist[afi][safi], p) == PREFIX_DENY)
+          return 0;
+      }
+
+  /* Output filter check. */
+  if (bgp_output_filter (peer, p, ri->attr, afi, safi) == FILTER_DENY)
+    {
+      if (BGP_DEBUG (filter, FILTER))
+	zlog (peer->log, LOG_INFO,
+	      "%s [Update:SEND] %s/%d is filtered",
+	      peer->host,
+	      inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+	      p->prefixlen);
+      return 0;
+    }
+
+#ifdef BGP_SEND_ASPATH_CHECK
+  /* AS path loop check. */
+  if (aspath_loop_check (ri->attr->aspath, peer->as))
+    {
+      if (BGP_DEBUG (filter, FILTER))  
+        zlog (peer->log, LOG_INFO, 
+	      "%s [Update:SEND] suppress announcement to peer AS %d is AS path.",
+	      peer->host, peer->as);
+      return 0;
+    }
+#endif /* BGP_SEND_ASPATH_CHECK */
+
+  /* If we're a CONFED we need to loop check the CONFED ID too */
+  if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
+    {
+      if (aspath_loop_check(ri->attr->aspath, bgp->confed_id))
+	{
+	  if (BGP_DEBUG (filter, FILTER))  
+	    zlog (peer->log, LOG_INFO, 
+		  "%s [Update:SEND] suppress announcement to peer AS %d is AS path.",
+		  peer->host,
+		  bgp->confed_id);
+	  return 0;
+	}      
+    }
+
+  /* Route-Reflect check. */
+  if (peer_sort (from) == BGP_PEER_IBGP && peer_sort (peer) == BGP_PEER_IBGP)
+    reflect = 1;
+  else
+    reflect = 0;
+
+  /* IBGP reflection check. */
+  if (reflect)
+    {
+      /* A route from a Client peer. */
+      if (CHECK_FLAG (from->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
+	{
+	  /* Reflect to all the Non-Client peers and also to the
+             Client peers other than the originator.  Originator check
+             is already done.  So there is noting to do. */
+	  /* no bgp client-to-client reflection check. */
+	  if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
+	    if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
+	      return 0;
+	}
+      else
+	{
+	  /* A route from a Non-client peer. Reflect to all other
+	     clients. */
+	  if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
+	    return 0;
+	}
+    }
+
+  /* For modify attribute, copy it to temporary structure. */
+  *attr = *ri->attr;
+
+  /* If local-preference is not set. */
+  if ((peer_sort (peer) == BGP_PEER_IBGP 
+       || peer_sort (peer) == BGP_PEER_CONFED) 
+      && (! (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))))
+    {
+      attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
+      attr->local_pref = bgp->default_local_pref;
+    }
+
+  /* Transparency check. */
+  if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
+      && CHECK_FLAG (from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
+    transparent = 1;
+  else
+    transparent = 0;
+
+  /* Remove MED if its an EBGP peer - will get overwritten by route-maps */
+  if (peer_sort (peer) == BGP_PEER_EBGP 
+      && attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
+    {
+      if (ri->peer != bgp->peer_self && ! transparent
+	  && ! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
+	attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC));
+    }
+
+  /* next-hop-set */
+  if (transparent || reflect
+      || (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
+	  && ((p->family == AF_INET && attr->nexthop.s_addr)
+	      || (p->family == AF_INET6 && ri->peer != bgp->peer_self))))
+    {
+      /* NEXT-HOP Unchanged. */
+    }
+  else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF)
+	   || (p->family == AF_INET && attr->nexthop.s_addr == 0)
+#ifdef HAVE_IPV6
+	   || (p->family == AF_INET6 && ri->peer == bgp->peer_self)
+#endif /* HAVE_IPV6 */
+	   || (peer_sort (peer) == BGP_PEER_EBGP
+	       && bgp_multiaccess_check_v4 (attr->nexthop, peer->host) == 0))
+    {
+      /* Set IPv4 nexthop. */
+      if (p->family == AF_INET)
+	{
+	  if (safi == SAFI_MPLS_VPN)
+	    memcpy (&attr->mp_nexthop_global_in, &peer->nexthop.v4, IPV4_MAX_BYTELEN);
+	  else
+	    memcpy (&attr->nexthop, &peer->nexthop.v4, IPV4_MAX_BYTELEN);
+	}
+#ifdef HAVE_IPV6
+      /* Set IPv6 nexthop. */
+      if (p->family == AF_INET6)
+	{
+	  /* IPv6 global nexthop must be included. */
+	  memcpy (&attr->mp_nexthop_global, &peer->nexthop.v6_global, 
+		  IPV6_MAX_BYTELEN);
+	  attr->mp_nexthop_len = 16;
+	}
+#endif /* HAVE_IPV6 */
+    }
+
+#ifdef HAVE_IPV6
+  if (p->family == AF_INET6)
+    {
+      /* Link-local address should not be transit to different peer. */
+      attr->mp_nexthop_len = 16;
+
+      /* Set link-local address for shared network peer. */
+      if (peer->shared_network 
+	  && ! IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_local))
+	{
+	  memcpy (&attr->mp_nexthop_local, &peer->nexthop.v6_local, 
+		  IPV6_MAX_BYTELEN);
+	  attr->mp_nexthop_len = 32;
+	}
+
+      /* If bgpd act as BGP-4+ route-reflector, do not send link-local
+	 address.*/
+      if (reflect)
+	attr->mp_nexthop_len = 16;
+
+      /* If BGP-4+ link-local nexthop is not link-local nexthop. */
+      if (! IN6_IS_ADDR_LINKLOCAL (&peer->nexthop.v6_local))
+	attr->mp_nexthop_len = 16;
+    }
+#endif /* HAVE_IPV6 */
+
+  /* If this is EBGP peer and remove-private-AS is set.  */
+  if (peer_sort (peer) == BGP_PEER_EBGP
+      && peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
+      && aspath_private_as_check (attr->aspath))
+    attr->aspath = aspath_empty_get ();
+
+  /* Route map & unsuppress-map apply. */
+  if (ROUTE_MAP_OUT_NAME (filter)
+      || ri->suppress)
+    {
+      info.peer = peer;
+      info.attr = attr;
+
+      /* The route reflector is not allowed to modify the attributes
+	 of the reflected IBGP routes. */
+      if (peer_sort (from) == BGP_PEER_IBGP 
+	  && peer_sort (peer) == BGP_PEER_IBGP)
+	{
+	  dummy_attr = *attr;
+	  info.attr = &dummy_attr;
+	}
+ 
+      if (ri->suppress)
+	ret = route_map_apply (UNSUPPRESS_MAP (filter), p, RMAP_BGP, &info);
+      else
+	ret = route_map_apply (ROUTE_MAP_OUT (filter), p, RMAP_BGP, &info);
+
+      if (ret == RMAP_DENYMATCH)
+	{
+	  bgp_attr_flush (attr);
+	  return 0;
+	}
+    }
+  return 1;
+}
+
+int
+bgp_process (struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
+{
+  struct prefix *p;
+  struct bgp_info *ri;
+  struct bgp_info *new_select;
+  struct bgp_info *old_select;
+  struct listnode *nn;
+  struct peer *peer;
+  struct attr attr;
+  struct bgp_info *ri1;
+  struct bgp_info *ri2;
+
+  p = &rn->p;
+
+  /* bgp deterministic-med */
+  new_select = NULL;
+  if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
+    for (ri1 = rn->info; ri1; ri1 = ri1->next)
+      {
+	if (CHECK_FLAG (ri1->flags, BGP_INFO_DMED_CHECK))
+	  continue;
+	if (BGP_INFO_HOLDDOWN (ri1))
+	  continue;
+
+	new_select = ri1;
+	if (ri1->next)
+	  for (ri2 = ri1->next; ri2; ri2 = ri2->next)
+	    {
+	      if (CHECK_FLAG (ri2->flags, BGP_INFO_DMED_CHECK))
+		continue;
+	      if (BGP_INFO_HOLDDOWN (ri2))
+		continue;
+
+	      if (aspath_cmp_left (ri1->attr->aspath, ri2->attr->aspath)
+		  || aspath_cmp_left_confed (ri1->attr->aspath,
+					     ri2->attr->aspath))
+		{
+		  if (bgp_info_cmp (bgp, ri2, new_select))
+		    {
+		      UNSET_FLAG (new_select->flags, BGP_INFO_DMED_SELECTED);
+		      new_select = ri2;
+		    }
+
+		  SET_FLAG (ri2->flags, BGP_INFO_DMED_CHECK);
+		}
+	    }
+	SET_FLAG (new_select->flags, BGP_INFO_DMED_CHECK);
+	SET_FLAG (new_select->flags, BGP_INFO_DMED_SELECTED);
+      }
+
+  /* Check old selected route and new selected route. */
+  old_select = NULL;
+  new_select = NULL;
+  for (ri = rn->info; ri; ri = ri->next)
+    {
+      if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED))
+	old_select = ri;
+
+      if (BGP_INFO_HOLDDOWN (ri))
+	continue;
+
+      if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED)
+          && (! CHECK_FLAG (ri->flags, BGP_INFO_DMED_SELECTED)))
+	{
+	  UNSET_FLAG (ri->flags, BGP_INFO_DMED_CHECK);
+	  continue;
+        }
+      UNSET_FLAG (ri->flags, BGP_INFO_DMED_CHECK);
+      UNSET_FLAG (ri->flags, BGP_INFO_DMED_SELECTED);
+
+      if (bgp_info_cmp (bgp, ri, new_select))
+	new_select = ri;
+    }
+
+  /* Nothing to do. */
+  if (old_select && old_select == new_select)
+    {
+      if (! CHECK_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED))
+	{
+	  if (CHECK_FLAG (old_select->flags, BGP_INFO_IGP_CHANGED))
+	    bgp_zebra_announce (p, old_select, bgp);
+	  return 0;
+	}
+    }
+
+  if (old_select)
+    UNSET_FLAG (old_select->flags, BGP_INFO_SELECTED);
+  if (new_select)
+    {
+      SET_FLAG (new_select->flags, BGP_INFO_SELECTED);
+      UNSET_FLAG (new_select->flags, BGP_INFO_ATTR_CHANGED);
+    }
+
+  /* Check each BGP peer. */
+  LIST_LOOP (bgp->peer, peer, nn)
+    {
+      /* Announce route to Established peer. */
+      if (peer->status != Established)
+	continue;
+
+      /* Address family configuration check. */
+      if (! peer->afc_nego[afi][safi])
+	continue;
+
+      /* First update is deferred until ORF or ROUTE-REFRESH is received */
+      if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH))
+	continue;
+
+      /* Announcement to peer->conf.  If the route is filtered,
+         withdraw it. */
+      if (new_select 
+	  && bgp_announce_check (new_select, peer, p, &attr, afi, safi))
+	bgp_adj_out_set (rn, peer, p, &attr, afi, safi, new_select);
+      else
+	bgp_adj_out_unset (rn, peer, p, afi, safi);
+    }
+
+  /* FIB update. */
+  if (safi == SAFI_UNICAST && ! bgp->name &&
+      ! bgp_option_check (BGP_OPT_NO_FIB))
+    {
+      if (new_select 
+	  && new_select->type == ZEBRA_ROUTE_BGP 
+	  && new_select->sub_type == BGP_ROUTE_NORMAL)
+	bgp_zebra_announce (p, new_select, bgp);
+      else
+	{
+	  /* Withdraw the route from the kernel. */
+	  if (old_select 
+	      && old_select->type == ZEBRA_ROUTE_BGP
+	      && old_select->sub_type == BGP_ROUTE_NORMAL)
+	    bgp_zebra_withdraw (p, old_select);
+	}
+    }
+  return 0;
+}
+
+int
+bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi, safi_t safi)
+{
+  if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)
+      && peer->pcount[afi][safi] >= peer->pmax[afi][safi])
+    {
+      zlog (peer->log, LOG_INFO,
+	    "MAXPFXEXCEED: No. of prefix received from %s (afi %d): %ld exceed limit %ld",
+	    peer->host, afi, peer->pcount[afi][safi], peer->pmax[afi][safi]);
+      if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
+	{
+	  char ndata[7];
+
+	  ndata[0] = (u_char)(afi >>  8);
+	  ndata[1] = (u_char) afi;
+	  ndata[3] = (u_char)(peer->pmax[afi][safi] >> 24);
+	  ndata[4] = (u_char)(peer->pmax[afi][safi] >> 16);
+	  ndata[5] = (u_char)(peer->pmax[afi][safi] >> 8);
+	  ndata[6] = (u_char)(peer->pmax[afi][safi]);
+
+	  if (safi == SAFI_MPLS_VPN)
+	    safi = BGP_SAFI_VPNV4;
+	  ndata[2] = (u_char) safi;
+
+	  bgp_notify_send_with_data (peer, BGP_NOTIFY_CEASE,
+				     BGP_NOTIFY_CEASE_MAX_PREFIX,
+				     ndata, 7);
+	  SET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
+	  return 1;
+	}
+    }
+  return 0;
+}
+
+void
+bgp_rib_remove (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer,
+		afi_t afi, safi_t safi)
+{
+  if (! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
+    {
+      peer->pcount[afi][safi]--;
+      bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi);
+      UNSET_FLAG (ri->flags, BGP_INFO_VALID);
+      bgp_process (peer->bgp, rn, afi, safi);
+    }
+  bgp_info_delete (rn, ri);
+  bgp_info_free (ri);
+  bgp_unlock_node (rn);
+}
+
+void
+bgp_rib_withdraw (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer,
+		  afi_t afi, safi_t safi, int force)
+{
+  int valid;
+  int status = BGP_DAMP_NONE;
+
+  if (! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
+    {
+      peer->pcount[afi][safi]--;
+      bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi);
+    }
+
+  if (! force)
+    {
+      if (CHECK_FLAG (peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
+	  && peer_sort (peer) == BGP_PEER_EBGP)
+	status = bgp_damp_withdraw (ri, rn, afi, safi, 0);
+
+      if (status == BGP_DAMP_SUPPRESSED)
+	return;
+    }
+
+  valid = CHECK_FLAG (ri->flags, BGP_INFO_VALID);
+  UNSET_FLAG (ri->flags, BGP_INFO_VALID);
+  bgp_process (peer->bgp, rn, afi, safi);
+
+  if (valid)
+    SET_FLAG (ri->flags, BGP_INFO_VALID);
+
+  if (status != BGP_DAMP_USED)
+    {
+      bgp_info_delete (rn, ri);
+      bgp_info_free (ri);
+      bgp_unlock_node (rn);
+    }
+}
+
+int
+bgp_update (struct peer *peer, struct prefix *p, struct attr *attr, 
+	    afi_t afi, safi_t safi, int type, int sub_type,
+	    struct prefix_rd *prd, u_char *tag, int soft_reconfig)
+{
+  int ret;
+  int aspath_loop_count = 0;
+  struct bgp_node *rn;
+  struct bgp *bgp;
+  struct attr new_attr;
+  struct attr *attr_new;
+  struct bgp_info *ri;
+  struct bgp_info *new;
+  char *reason;
+  char buf[SU_ADDRSTRLEN];
+
+  bgp = peer->bgp;
+  rn = bgp_afi_node_get (bgp, afi, safi, p, prd);
+
+  /* When peer's soft reconfiguration enabled.  Record input packet in
+     Adj-RIBs-In.  */
+  if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
+      && peer != bgp->peer_self && ! soft_reconfig)
+    bgp_adj_in_set (rn, peer, attr);
+
+  /* Check previously received route. */
+  for (ri = rn->info; ri; ri = ri->next)
+    if (ri->peer == peer && ri->type == type && ri->sub_type == sub_type)
+      break;
+
+  /* AS path local-as loop check. */
+  if (peer->change_local_as)
+    {
+      if (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
+	aspath_loop_count = 1;
+
+      if (aspath_loop_check (attr->aspath, peer->change_local_as) > aspath_loop_count) 
+	{
+	  reason = "as-path contains our own AS;";
+	  goto filtered;
+	}
+    }
+
+  /* AS path loop check. */
+  if (aspath_loop_check (attr->aspath, bgp->as) > peer->allowas_in[afi][safi]
+      || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
+	  && aspath_loop_check(attr->aspath, bgp->confed_id)
+	  > peer->allowas_in[afi][safi]))
+    {
+      reason = "as-path contains our own AS;";
+      goto filtered;
+    }
+
+  /* Route reflector originator ID check.  */
+  if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID)
+      && IPV4_ADDR_SAME (&bgp->router_id, &attr->originator_id))
+    {
+      reason = "originator is us;";
+      goto filtered;
+    }
+
+  /* Route reflector cluster ID check.  */
+  if (bgp_cluster_filter (peer, attr))
+    {
+      reason = "reflected from the same cluster;";
+      goto  filtered;
+    }
+
+  /* Apply incoming filter.  */
+  if (bgp_input_filter (peer, p, attr, afi, safi) == FILTER_DENY)
+    {
+      reason = "filter;";
+      goto filtered;
+    }
+
+  /* Apply incoming route-map. */
+  new_attr = *attr;
+
+  if (bgp_input_modifier (peer, p, &new_attr, afi, safi) == RMAP_DENY)
+    {
+      reason = "route-map;";
+      goto filtered;
+    }
+
+  /* IPv4 unicast next hop check.  */
+  if (afi == AFI_IP && safi == SAFI_UNICAST)
+    {
+      /* If the peer is EBGP and nexthop is not on connected route,
+	 discard it.  */
+      if (peer_sort (peer) == BGP_PEER_EBGP && peer->ttl == 1
+	  && ! bgp_nexthop_check_ebgp (afi, &new_attr)
+	  && ! CHECK_FLAG (peer->flags, PEER_FLAG_ENFORCE_MULTIHOP))
+	{
+	  reason = "non-connected next-hop;";
+	  goto filtered;
+	}
+
+      /* Next hop must not be 0.0.0.0 nor Class E address.  Next hop
+	 must not be my own address.  */
+      if (bgp_nexthop_self (afi, &new_attr)
+	  || new_attr.nexthop.s_addr == 0
+	  || ntohl (new_attr.nexthop.s_addr) >= 0xe0000000)
+	{
+	  reason = "martian next-hop;";
+	  goto filtered;
+	}
+    }
+
+  attr_new = bgp_attr_intern (&new_attr);
+
+  /* If the update is implicit withdraw. */
+  if (ri)
+    {
+      ri->uptime = time (NULL);
+
+      /* Same attribute comes in. */
+      if (attrhash_cmp (ri->attr, attr_new))
+	{
+	  UNSET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+
+	  if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
+	      && peer_sort (peer) == BGP_PEER_EBGP
+	      && CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
+	    {
+	      if (BGP_DEBUG (update, UPDATE_IN))  
+		  zlog (peer->log, LOG_INFO, "%s rcvd %s/%d",
+		  peer->host,
+		  inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+		  p->prefixlen);
+
+	      peer->pcount[afi][safi]++;
+	      ret = bgp_damp_update (ri, rn, afi, safi);
+	      if (ret != BGP_DAMP_SUPPRESSED)
+		{
+		  bgp_aggregate_increment (bgp, p, ri, afi, safi);
+		  bgp_process (bgp, rn, afi, safi);
+		}
+	    }
+	  else
+	    {
+	      if (BGP_DEBUG (update, UPDATE_IN))  
+		zlog (peer->log, LOG_INFO,
+		"%s rcvd %s/%d...duplicate ignored",
+		peer->host,
+		inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+		p->prefixlen);
+	    }
+
+	  bgp_unlock_node (rn);
+	  bgp_attr_unintern (attr_new);
+	  return 0;
+	}
+
+      /* Received Logging. */
+      if (BGP_DEBUG (update, UPDATE_IN))  
+	zlog (peer->log, LOG_INFO, "%s rcvd %s/%d",
+	      peer->host,
+	      inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+	      p->prefixlen);
+
+      /* The attribute is changed. */
+      SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+
+      /* Update bgp route dampening information.  */
+      if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
+	  && peer_sort (peer) == BGP_PEER_EBGP)
+	{
+	  /* This is implicit withdraw so we should update dampening
+	     information.  */
+	  if (! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
+	    bgp_damp_withdraw (ri, rn, afi, safi, 1);  
+	  else
+	    peer->pcount[afi][safi]++;
+	}
+	
+      bgp_aggregate_decrement (bgp, p, ri, afi, safi);
+
+      /* Update to new attribute.  */
+      bgp_attr_unintern (ri->attr);
+      ri->attr = attr_new;
+
+      /* Update MPLS tag.  */
+      if (safi == SAFI_MPLS_VPN)
+	memcpy (ri->tag, tag, 3);
+
+      /* Update bgp route dampening information.  */
+      if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
+	  && peer_sort (peer) == BGP_PEER_EBGP)
+	{
+	  /* Now we do normal update dampening.  */
+	  ret = bgp_damp_update (ri, rn, afi, safi);
+	  if (ret == BGP_DAMP_SUPPRESSED)
+	    {
+	      bgp_unlock_node (rn);
+	      return 0;
+	    }
+	}
+
+      /* Nexthop reachability check. */
+      if ((afi == AFI_IP || afi == AFI_IP6)
+	  && safi == SAFI_UNICAST 
+	  && (peer_sort (peer) == BGP_PEER_IBGP
+	      || (peer_sort (peer) == BGP_PEER_EBGP && peer->ttl != 1)
+	      || CHECK_FLAG (peer->flags, PEER_FLAG_ENFORCE_MULTIHOP)))
+	{
+	  if (bgp_nexthop_lookup (afi, peer, ri, NULL, NULL))
+	    SET_FLAG (ri->flags, BGP_INFO_VALID);
+	  else
+	    UNSET_FLAG (ri->flags, BGP_INFO_VALID);
+	}
+      else
+	SET_FLAG (ri->flags, BGP_INFO_VALID);
+
+      /* Process change. */
+      bgp_aggregate_increment (bgp, p, ri, afi, safi);
+
+      bgp_process (bgp, rn, afi, safi);
+      bgp_unlock_node (rn);
+      return 0;
+    }
+
+  /* Received Logging. */
+  if (BGP_DEBUG (update, UPDATE_IN))  
+    {
+      zlog (peer->log, LOG_INFO, "%s rcvd %s/%d",
+	    peer->host,
+	    inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+	    p->prefixlen);
+    }
+
+  /* Increment prefix counter */
+  peer->pcount[afi][safi]++;
+
+  /* Make new BGP info. */
+  new = bgp_info_new ();
+  new->type = type;
+  new->sub_type = sub_type;
+  new->peer = peer;
+  new->attr = attr_new;
+  new->uptime = time (NULL);
+
+  /* Update MPLS tag. */
+  if (safi == SAFI_MPLS_VPN)
+    memcpy (new->tag, tag, 3);
+
+  /* Nexthop reachability check. */
+  if ((afi == AFI_IP || afi == AFI_IP6)
+      && safi == SAFI_UNICAST
+      && (peer_sort (peer) == BGP_PEER_IBGP
+	  || (peer_sort (peer) == BGP_PEER_EBGP && peer->ttl != 1)
+	  || CHECK_FLAG (peer->flags, PEER_FLAG_ENFORCE_MULTIHOP)))
+    {
+      if (bgp_nexthop_lookup (afi, peer, new, NULL, NULL))
+	SET_FLAG (new->flags, BGP_INFO_VALID);
+      else
+	UNSET_FLAG (new->flags, BGP_INFO_VALID);
+    }
+  else
+    SET_FLAG (new->flags, BGP_INFO_VALID);
+
+  /* Aggregate address increment. */
+  bgp_aggregate_increment (bgp, p, new, afi, safi);
+  
+  /* Register new BGP information. */
+  bgp_info_add (rn, new);
+
+  /* If maximum prefix count is configured and current prefix
+     count exeed it. */
+  if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
+    if (bgp_maximum_prefix_overflow (peer, afi, safi))
+      return -1;
+
+  /* Process change. */
+  bgp_process (bgp, rn, afi, safi);
+
+  return 0;
+
+  /* This BGP update is filtered.  Log the reason then update BGP
+     entry.  */
+ filtered:
+  if (BGP_DEBUG (update, UPDATE_IN))
+    zlog (peer->log, LOG_INFO,
+	  "%s rcvd UPDATE about %s/%d -- DENIED due to: %s",
+	  peer->host,
+	  inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+	  p->prefixlen, reason);
+
+  if (ri)
+    bgp_rib_withdraw (rn, ri, peer, afi, safi, 1);
+
+  bgp_unlock_node (rn);
+
+  return 0;
+}
+
+int
+bgp_withdraw (struct peer *peer, struct prefix *p, struct attr *attr, 
+	     int afi, int safi, int type, int sub_type, struct prefix_rd *prd,
+	      u_char *tag)
+{
+  struct bgp *bgp;
+  char buf[SU_ADDRSTRLEN];
+  struct bgp_node *rn;
+  struct bgp_info *ri;
+
+  bgp = peer->bgp;
+
+  /* Logging. */
+  if (BGP_DEBUG (update, UPDATE_IN))  
+    zlog (peer->log, LOG_INFO, "%s rcvd UPDATE about %s/%d -- withdrawn",
+	  peer->host,
+	  inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+	  p->prefixlen);
+
+  /* Lookup node. */
+  rn = bgp_afi_node_get (bgp, afi, safi, p, prd);
+
+  /* If peer is soft reconfiguration enabled.  Record input packet for
+     further calculation. */
+  if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
+      && peer != bgp->peer_self)
+    bgp_adj_in_unset (rn, peer);
+
+  /* Lookup withdrawn route. */
+  for (ri = rn->info; ri; ri = ri->next)
+    if (ri->peer == peer && ri->type == type && ri->sub_type == sub_type)
+      break;
+
+  /* Withdraw specified route from routing table. */
+  if (ri && ! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
+    bgp_rib_withdraw (rn, ri, peer, afi, safi, 0);
+  else if (BGP_DEBUG (update, UPDATE_IN))
+    zlog (peer->log, LOG_INFO, 
+	  "%s Can't find the route %s/%d", peer->host,
+	  inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+	  p->prefixlen);
+
+  /* Unlock bgp_node_get() lock. */
+  bgp_unlock_node (rn);
+
+  return 0;
+}
+
+void
+bgp_default_originate (struct peer *peer, afi_t afi, safi_t safi, int withdraw)
+{
+  struct bgp *bgp;
+  struct attr attr;
+  struct aspath *aspath;
+  struct prefix p;
+  struct bgp_info binfo;
+  struct peer *from;
+  int ret = RMAP_DENYMATCH;
+
+  bgp = peer->bgp;
+  from = bgp->peer_self;
+
+  bgp_attr_default_set (&attr, BGP_ORIGIN_IGP);
+  aspath = attr.aspath;
+  attr.local_pref = bgp->default_local_pref;
+  memcpy (&attr.nexthop, &peer->nexthop.v4, IPV4_MAX_BYTELEN);
+
+  if (afi == AFI_IP)
+    str2prefix ("0.0.0.0/0", &p);
+#ifdef HAVE_IPV6
+  else if (afi == AFI_IP6)
+    {
+      str2prefix ("::/0", &p);
+
+      /* IPv6 global nexthop must be included. */
+      memcpy (&attr.mp_nexthop_global, &peer->nexthop.v6_global, 
+	      IPV6_MAX_BYTELEN);
+	      attr.mp_nexthop_len = 16;
+ 
+      /* If the peer is on shared nextwork and we have link-local
+	 nexthop set it. */
+      if (peer->shared_network 
+	  && !IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_local))
+	{
+	  memcpy (&attr.mp_nexthop_local, &peer->nexthop.v6_local, 
+		  IPV6_MAX_BYTELEN);
+	  attr.mp_nexthop_len = 32;
+	}
+    }
+#endif /* HAVE_IPV6 */
+  else
+    return;
+
+  if (peer->default_rmap[afi][safi].name)
+    {
+      binfo.peer = bgp->peer_self;
+      binfo.attr = &attr;
+
+      ret = route_map_apply (peer->default_rmap[afi][safi].map, &p,
+			     RMAP_BGP, &binfo);
+
+      if (ret == RMAP_DENYMATCH)
+	{
+	  bgp_attr_flush (&attr);
+	  withdraw = 1;
+	}
+    }
+
+  if (withdraw)
+    {
+      if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE))
+	bgp_default_withdraw_send (peer, afi, safi);
+      UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE);
+    }
+  else
+    {
+      SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE);
+      bgp_default_update_send (peer, &attr, afi, safi, from);
+    }
+
+  aspath_unintern (aspath);
+}
+
+static void
+bgp_announce_table (struct peer *peer, afi_t afi, safi_t safi,
+		    struct bgp_table *table)
+{
+  struct bgp_node *rn;
+  struct bgp_info *ri;
+  struct attr attr;
+
+  if (! table)
+    table = peer->bgp->rib[afi][safi];
+
+  if (safi != SAFI_MPLS_VPN
+      && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
+    bgp_default_originate (peer, afi, safi, 0);
+
+  for (rn = bgp_table_top (table); rn; rn = bgp_route_next(rn))
+    for (ri = rn->info; ri; ri = ri->next)
+      if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) && ri->peer != peer)
+	{
+	  if (bgp_announce_check (ri, peer, &rn->p, &attr, afi, safi))
+	    bgp_adj_out_set (rn, peer, &rn->p, &attr, afi, safi, ri);
+	  else
+	    bgp_adj_out_unset (rn, peer, &rn->p, afi, safi);
+	}
+}
+
+void
+bgp_announce_route (struct peer *peer, afi_t afi, safi_t safi)
+{
+  struct bgp_node *rn;
+  struct bgp_table *table;
+
+  if (peer->status != Established)
+    return;
+
+  if (! peer->afc_nego[afi][safi])
+    return;
+
+  /* First update is deferred until ORF or ROUTE-REFRESH is received */
+  if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH))
+    return;
+
+  if (safi != SAFI_MPLS_VPN)
+    bgp_announce_table (peer, afi, safi, NULL);
+  else
+    for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn;
+	 rn = bgp_route_next(rn))
+      if ((table = (rn->info)) != NULL)
+	bgp_announce_table (peer, afi, safi, table);
+}
+
+void
+bgp_announce_route_all (struct peer *peer)
+{
+  afi_t afi;
+  safi_t safi;
+  
+  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+      bgp_announce_route (peer, afi, safi);
+}
+
+static void
+bgp_soft_reconfig_table (struct peer *peer, afi_t afi, safi_t safi,
+			 struct bgp_table *table)
+{
+  int ret;
+  struct bgp_node *rn;
+  struct bgp_adj_in *ain;
+
+  if (! table)
+    table = peer->bgp->rib[afi][safi];
+
+  for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
+    for (ain = rn->adj_in; ain; ain = ain->next)
+      {
+	if (ain->peer == peer)
+	  {
+	    ret = bgp_update (peer, &rn->p, ain->attr, afi, safi,
+			      ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
+			      NULL, NULL, 1);
+	    if (ret < 0)
+	      {
+		bgp_unlock_node (rn);
+		return;
+	      }
+	    continue;
+	  }
+      }
+}
+
+void
+bgp_soft_reconfig_in (struct peer *peer, afi_t afi, safi_t safi)
+{
+  struct bgp_node *rn;
+  struct bgp_table *table;
+
+  if (peer->status != Established)
+    return;
+
+  if (safi != SAFI_MPLS_VPN)
+    bgp_soft_reconfig_table (peer, afi, safi, NULL);
+  else
+    for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn;
+	 rn = bgp_route_next (rn))
+      if ((table = rn->info) != NULL)
+	bgp_soft_reconfig_table (peer, afi, safi, table);
+}
+
+static void
+bgp_clear_route_table (struct peer *peer, afi_t afi, safi_t safi,
+		       struct bgp_table *table)
+{
+  struct bgp_node *rn;
+  struct bgp_adj_in *ain;
+  struct bgp_adj_out *aout;
+  struct bgp_info *ri;
+
+  if (! table)
+    table = peer->bgp->rib[afi][safi];
+
+  for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
+    {
+      for (ri = rn->info; ri; ri = ri->next)
+	if (ri->peer == peer)
+	  {
+	    bgp_rib_remove (rn, ri, peer, afi, safi);
+	    break;
+	  }
+      for (ain = rn->adj_in; ain; ain = ain->next)
+	if (ain->peer == peer)
+	  {
+	    bgp_adj_in_remove (rn, ain);
+	    bgp_unlock_node (rn);
+	    break;
+	  }
+      for (aout = rn->adj_out; aout; aout = aout->next)
+	if (aout->peer == peer)
+	  {
+	    bgp_adj_out_remove (rn, aout, peer, afi, safi);
+	    bgp_unlock_node (rn);
+	    break;
+	  }
+    }
+}
+
+void
+bgp_clear_route (struct peer *peer, afi_t afi, safi_t safi)
+{
+  struct bgp_node *rn;
+  struct bgp_table *table;
+
+  if (! peer->afc[afi][safi])
+    return;
+
+  if (safi != SAFI_MPLS_VPN)
+    bgp_clear_route_table (peer, afi, safi, NULL);
+  else
+    for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn;
+	 rn = bgp_route_next (rn))
+      if ((table = rn->info) != NULL)
+	bgp_clear_route_table (peer, afi, safi, table);
+}
+  
+void
+bgp_clear_route_all (struct peer *peer)
+{
+  afi_t afi;
+  safi_t safi;
+
+  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+      bgp_clear_route (peer, afi, safi);
+}
+
+void
+bgp_clear_adj_in (struct peer *peer, afi_t afi, safi_t safi)
+{
+  struct bgp_table *table;
+  struct bgp_node *rn;
+  struct bgp_adj_in *ain;
+
+  table = peer->bgp->rib[afi][safi];
+
+  for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
+    for (ain = rn->adj_in; ain ; ain = ain->next)
+      if (ain->peer == peer)
+	{
+          bgp_adj_in_remove (rn, ain);
+          bgp_unlock_node (rn);
+          break;
+	}
+}
+
+/* Delete all kernel routes. */
+void
+bgp_terminate ()
+{
+  struct bgp *bgp;
+  struct listnode *nn;
+  struct bgp_node *rn;
+  struct bgp_table *table;
+  struct bgp_info *ri;
+
+  LIST_LOOP (bm->bgp, bgp, nn)
+    {
+      table = bgp->rib[AFI_IP][SAFI_UNICAST];
+
+      for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
+	for (ri = rn->info; ri; ri = ri->next)
+	  if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)
+	      && ri->type == ZEBRA_ROUTE_BGP 
+	      && ri->sub_type == BGP_ROUTE_NORMAL)
+	    bgp_zebra_withdraw (&rn->p, ri);
+
+      table = bgp->rib[AFI_IP6][SAFI_UNICAST];
+
+      for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
+	for (ri = rn->info; ri; ri = ri->next)
+	  if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)
+	      && ri->type == ZEBRA_ROUTE_BGP 
+	      && ri->sub_type == BGP_ROUTE_NORMAL)
+	    bgp_zebra_withdraw (&rn->p, ri);
+    }
+}
+
+void
+bgp_reset ()
+{
+  vty_reset ();
+  bgp_zclient_reset ();
+  access_list_reset ();
+  prefix_list_reset ();
+}
+
+/* Parse NLRI stream.  Withdraw NLRI is recognized by NULL attr
+   value. */
+int
+bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet)
+{
+  u_char *pnt;
+  u_char *lim;
+  struct prefix p;
+  int psize;
+  int ret;
+
+  /* Check peer status. */
+  if (peer->status != Established)
+    return 0;
+  
+  pnt = packet->nlri;
+  lim = pnt + packet->length;
+
+  for (; pnt < lim; pnt += psize)
+    {
+      /* Clear prefix structure. */
+      memset (&p, 0, sizeof (struct prefix));
+
+      /* Fetch prefix length. */
+      p.prefixlen = *pnt++;
+      p.family = afi2family (packet->afi);
+      
+      /* Already checked in nlri_sanity_check().  We do double check
+         here. */
+      if ((packet->afi == AFI_IP && p.prefixlen > 32)
+	  || (packet->afi == AFI_IP6 && p.prefixlen > 128))
+	return -1;
+
+      /* Packet size overflow check. */
+      psize = PSIZE (p.prefixlen);
+
+      /* When packet overflow occur return immediately. */
+      if (pnt + psize > lim)
+	return -1;
+
+      /* Fetch prefix from NLRI packet. */
+      memcpy (&p.u.prefix, pnt, psize);
+
+      /* Check address. */
+      if (packet->afi == AFI_IP && packet->safi == SAFI_UNICAST)
+	{
+	  if (IN_CLASSD (ntohl (p.u.prefix4.s_addr)))
+	    {
+	      zlog (peer->log, LOG_ERR, 
+		    "IPv4 unicast NLRI is multicast address %s",
+		    inet_ntoa (p.u.prefix4));
+	      bgp_notify_send (peer, 
+			       BGP_NOTIFY_UPDATE_ERR, 
+			       BGP_NOTIFY_UPDATE_INVAL_NETWORK);
+	      return -1;
+	    }
+	}
+
+#ifdef HAVE_IPV6
+      /* Check address. */
+      if (packet->afi == AFI_IP6 && packet->safi == SAFI_UNICAST)
+	{
+	  if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
+	    {
+	      char buf[BUFSIZ];
+
+	      zlog (peer->log, LOG_WARNING, 
+		    "IPv6 link-local NLRI received %s ignore this NLRI",
+		    inet_ntop (AF_INET6, &p.u.prefix6, buf, BUFSIZ));
+
+	      continue;
+	    }
+	}
+#endif /* HAVE_IPV6 */
+
+      /* Normal process. */
+      if (attr)
+	ret = bgp_update (peer, &p, attr, packet->afi, packet->safi, 
+			  ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL, 0);
+      else
+	ret = bgp_withdraw (peer, &p, attr, packet->afi, packet->safi, 
+			    ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL);
+
+      /* Address family configuration mismatch or maximum-prefix count
+         overflow. */
+      if (ret < 0)
+	return -1;
+    }
+
+  /* Packet length consistency check. */
+  if (pnt != lim)
+    return -1;
+
+  return 0;
+}
+
+/* NLRI encode syntax check routine. */
+int
+bgp_nlri_sanity_check (struct peer *peer, int afi, u_char *pnt,
+		       bgp_size_t length)
+{
+  u_char *end;
+  u_char prefixlen;
+  int psize;
+
+  end = pnt + length;
+
+  /* RFC1771 6.3 The NLRI field in the UPDATE message is checked for
+     syntactic validity.  If the field is syntactically incorrect,
+     then the Error Subcode is set to Invalid Network Field. */
+
+  while (pnt < end)
+    {
+      prefixlen = *pnt++;
+      
+      /* Prefix length check. */
+      if ((afi == AFI_IP && prefixlen > 32)
+	  || (afi == AFI_IP6 && prefixlen > 128))
+	{
+	  plog_err (peer->log, 
+		    "%s [Error] Update packet error (wrong prefix length %d)",
+		    peer->host, prefixlen);
+	  bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, 
+			   BGP_NOTIFY_UPDATE_INVAL_NETWORK);
+	  return -1;
+	}
+
+      /* Packet size overflow check. */
+      psize = PSIZE (prefixlen);
+
+      if (pnt + psize > end)
+	{
+	  plog_err (peer->log, 
+		    "%s [Error] Update packet error"
+		    " (prefix data overflow prefix size is %d)",
+		    peer->host, psize);
+	  bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, 
+			   BGP_NOTIFY_UPDATE_INVAL_NETWORK);
+	  return -1;
+	}
+
+      pnt += psize;
+    }
+
+  /* Packet length consistency check. */
+  if (pnt != end)
+    {
+      plog_err (peer->log,
+		"%s [Error] Update packet error"
+		" (prefix length mismatch with total length)",
+		peer->host);
+      bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, 
+		       BGP_NOTIFY_UPDATE_INVAL_NETWORK);
+      return -1;
+    }
+  return 0;
+}
+
+struct bgp_static *
+bgp_static_new ()
+{
+  struct bgp_static *new;
+  new = XMALLOC (MTYPE_BGP_STATIC, sizeof (struct bgp_static));
+  memset (new, 0, sizeof (struct bgp_static));
+  return new;
+}
+
+void
+bgp_static_free (struct bgp_static *bgp_static)
+{
+  if (bgp_static->rmap.name)
+    free (bgp_static->rmap.name);
+  XFREE (MTYPE_BGP_STATIC, bgp_static);
+}
+
+void
+bgp_static_update (struct bgp *bgp, struct prefix *p,
+		   struct bgp_static *bgp_static, afi_t afi, safi_t safi)
+{
+  struct bgp_node *rn;
+  struct bgp_info *ri;
+  struct bgp_info *new;
+  struct bgp_info info;
+  struct attr attr;
+  struct attr *attr_new;
+  int ret;
+
+  rn = bgp_afi_node_get (bgp, afi, safi, p, NULL);
+
+  bgp_attr_default_set (&attr, BGP_ORIGIN_IGP);
+  if (bgp_static)
+    {
+      attr.nexthop = bgp_static->igpnexthop;
+      attr.med = bgp_static->igpmetric;
+      attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
+    }
+
+  /* Apply route-map. */
+  if (bgp_static->rmap.name)
+    {
+      info.peer = bgp->peer_self;
+      info.attr = &attr;
+
+      ret = route_map_apply (bgp_static->rmap.map, p, RMAP_BGP, &info);
+      if (ret == RMAP_DENYMATCH)
+	{    
+	  /* Free uninterned attribute. */
+	  bgp_attr_flush (&attr);
+
+	  /* Unintern original. */
+	  aspath_unintern (attr.aspath);
+	  bgp_static_withdraw (bgp, p, afi, safi);
+	  return;
+	}
+    }
+
+  attr_new = bgp_attr_intern (&attr);
+
+  for (ri = rn->info; ri; ri = ri->next)
+    if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
+	&& ri->sub_type == BGP_ROUTE_STATIC)
+      break;
+
+  if (ri)
+    {
+      if (attrhash_cmp (ri->attr, attr_new))
+	{
+	  bgp_unlock_node (rn);
+	  bgp_attr_unintern (attr_new);
+	  aspath_unintern (attr.aspath);
+	  return;
+	}
+      else
+	{
+	  /* The attribute is changed. */
+	  SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+
+	  /* Rewrite BGP route information. */
+	  bgp_aggregate_decrement (bgp, p, ri, afi, safi);
+	  bgp_attr_unintern (ri->attr);
+	  ri->attr = attr_new;
+	  ri->uptime = time (NULL);
+
+	  /* Process change. */
+	  bgp_aggregate_increment (bgp, p, ri, afi, safi);
+	  bgp_process (bgp, rn, afi, safi);
+	  bgp_unlock_node (rn);
+	  aspath_unintern (attr.aspath);
+	  return;
+	}
+    }
+
+  /* Make new BGP info. */
+  new = bgp_info_new ();
+  new->type = ZEBRA_ROUTE_BGP;
+  new->sub_type = BGP_ROUTE_STATIC;
+  new->peer = bgp->peer_self;
+  SET_FLAG (new->flags, BGP_INFO_VALID);
+  new->attr = attr_new;
+  new->uptime = time (NULL);
+
+  /* Aggregate address increment. */
+  bgp_aggregate_increment (bgp, p, new, afi, safi);
+  
+  /* Register new BGP information. */
+  bgp_info_add (rn, new);
+
+  /* Process change. */
+  bgp_process (bgp, rn, afi, safi);
+
+  /* Unintern original. */
+  aspath_unintern (attr.aspath);
+}
+
+void
+bgp_static_update_vpnv4 (struct bgp *bgp, struct prefix *p, u_int16_t afi,
+			 u_char safi, struct prefix_rd *prd, u_char *tag)
+{
+  struct bgp_node *rn;
+  struct bgp_info *new;
+
+  rn = bgp_afi_node_get (bgp, afi, safi, p, prd);
+
+  /* Make new BGP info. */
+  new = bgp_info_new ();
+  new->type = ZEBRA_ROUTE_BGP;
+  new->sub_type = BGP_ROUTE_STATIC;
+  new->peer = bgp->peer_self;
+  new->attr = bgp_attr_default_intern (BGP_ORIGIN_IGP);
+  SET_FLAG (new->flags, BGP_INFO_VALID);
+  new->uptime = time (NULL);
+  memcpy (new->tag, tag, 3);
+
+  /* Aggregate address increment. */
+  bgp_aggregate_increment (bgp, p, (struct bgp_info *) new, afi, safi);
+  
+  /* Register new BGP information. */
+  bgp_info_add (rn, (struct bgp_info *) new);
+
+  /* Process change. */
+  bgp_process (bgp, rn, afi, safi);
+}
+
+void
+bgp_static_withdraw (struct bgp *bgp, struct prefix *p, afi_t afi,
+		     safi_t safi)
+{
+  struct bgp_node *rn;
+  struct bgp_info *ri;
+
+  rn = bgp_afi_node_get (bgp, afi, safi, p, NULL);
+
+  /* Check selected route and self inserted route. */
+  for (ri = rn->info; ri; ri = ri->next)
+    if (ri->peer == bgp->peer_self 
+	&& ri->type == ZEBRA_ROUTE_BGP
+	&& ri->sub_type == BGP_ROUTE_STATIC)
+      break;
+
+  /* Withdraw static BGP route from routing table. */
+  if (ri)
+    {
+      bgp_aggregate_decrement (bgp, p, ri, afi, safi);
+      UNSET_FLAG (ri->flags, BGP_INFO_VALID);
+      bgp_process (bgp, rn, afi, safi);
+      bgp_info_delete (rn, ri);
+      bgp_info_free (ri);
+      bgp_unlock_node (rn);
+    }
+
+  /* Unlock bgp_node_lookup. */
+  bgp_unlock_node (rn);
+}
+
+void
+bgp_static_withdraw_vpnv4 (struct bgp *bgp, struct prefix *p, u_int16_t afi,
+			   u_char safi, struct prefix_rd *prd, u_char *tag)
+{
+  struct bgp_node *rn;
+  struct bgp_info *ri;
+
+  rn = bgp_afi_node_get (bgp, afi, safi, p, prd);
+
+  /* Check selected route and self inserted route. */
+  for (ri = rn->info; ri; ri = ri->next)
+    if (ri->peer == bgp->peer_self 
+	&& ri->type == ZEBRA_ROUTE_BGP
+	&& ri->sub_type == BGP_ROUTE_STATIC)
+      break;
+
+  /* Withdraw static BGP route from routing table. */
+  if (ri)
+    {
+      bgp_aggregate_decrement (bgp, p, ri, afi, safi);
+      UNSET_FLAG (ri->flags, BGP_INFO_VALID);
+      bgp_process (bgp, rn, afi, safi);
+      bgp_info_delete (rn, ri);
+      bgp_info_free (ri);
+      bgp_unlock_node (rn);
+    }
+
+  /* Unlock bgp_node_lookup. */
+  bgp_unlock_node (rn);
+}
+
+/* Configure static BGP network.  When user don't run zebra, static
+   route should be installed as valid.  */
+int
+bgp_static_set (struct vty *vty, struct bgp *bgp, char *ip_str, u_int16_t afi,
+		u_char safi, char *rmap, int backdoor)
+{
+  int ret;
+  struct prefix p;
+  struct bgp_static *bgp_static;
+  struct bgp_node *rn;
+  int need_update = 0;
+
+  /* Convert IP prefix string to struct prefix. */
+  ret = str2prefix (ip_str, &p);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed prefix%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+#ifdef HAVE_IPV6
+  if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
+    {
+      vty_out (vty, "%% Malformed prefix (link-local address)%s",
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+#endif /* HAVE_IPV6 */
+
+  apply_mask (&p);
+
+  /* Set BGP static route configuration. */
+  rn = bgp_node_get (bgp->route[afi][safi], &p);
+
+  if (rn->info)
+    {
+      /* Configuration change. */
+      bgp_static = rn->info;
+
+      /* Check previous routes are installed into BGP.  */
+      if (! bgp_static->backdoor && bgp_static->valid)
+	need_update = 1;
+
+      bgp_static->backdoor = backdoor;
+      if (rmap)
+	{
+	  if (bgp_static->rmap.name)
+	    free (bgp_static->rmap.name);
+	  bgp_static->rmap.name = strdup (rmap);
+	  bgp_static->rmap.map = route_map_lookup_by_name (rmap);
+	}
+      else
+	{
+	  if (bgp_static->rmap.name)
+	    free (bgp_static->rmap.name);
+	  bgp_static->rmap.name = NULL;
+	  bgp_static->rmap.map = NULL;
+	  bgp_static->valid = 0;
+	}
+      bgp_unlock_node (rn);
+    }
+  else
+    {
+      /* New configuration. */
+      bgp_static = bgp_static_new ();
+      bgp_static->backdoor = backdoor;
+      bgp_static->valid = 0;
+      bgp_static->igpmetric = 0;
+      bgp_static->igpnexthop.s_addr = 0;
+      if (rmap)
+	{
+	  if (bgp_static->rmap.name)
+	    free (bgp_static->rmap.name);
+	  bgp_static->rmap.name = strdup (rmap);
+	  bgp_static->rmap.map = route_map_lookup_by_name (rmap);
+	}
+      rn->info = bgp_static;
+    }
+
+  /* If BGP scan is not enabled, we should install this route here.  */
+  if (! bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
+    {
+      bgp_static->valid = 1;
+
+      if (need_update)
+	bgp_static_withdraw (bgp, &p, afi, safi);
+
+      if (! bgp_static->backdoor)
+	bgp_static_update (bgp, &p, bgp_static, afi, safi);
+    }
+
+  return CMD_SUCCESS;
+}
+
+/* Configure static BGP network. */
+int
+bgp_static_unset (struct vty *vty, struct bgp *bgp, char *ip_str,
+		  u_int16_t afi, u_char safi)
+{
+  int ret;
+  struct prefix p;
+  struct bgp_static *bgp_static;
+  struct bgp_node *rn;
+
+  /* Convert IP prefix string to struct prefix. */
+  ret = str2prefix (ip_str, &p);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed prefix%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+#ifdef HAVE_IPV6
+  if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
+    {
+      vty_out (vty, "%% Malformed prefix (link-local address)%s",
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+#endif /* HAVE_IPV6 */
+
+  apply_mask (&p);
+
+  rn = bgp_node_lookup (bgp->route[afi][safi], &p);
+  if (! rn)
+    {
+      vty_out (vty, "%% Can't find specified static route configuration.%s",
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  bgp_static = rn->info;
+
+  /* Update BGP RIB. */
+  if (! bgp_static->backdoor)
+    bgp_static_withdraw (bgp, &p, afi, safi);
+
+  /* Clear configuration. */
+  bgp_static_free (bgp_static);
+  rn->info = NULL;
+  bgp_unlock_node (rn);
+  bgp_unlock_node (rn);
+
+  return CMD_SUCCESS;
+}
+
+/* Called from bgp_delete().  Delete all static routes from the BGP
+   instance. */
+void
+bgp_static_delete (struct bgp *bgp)
+{
+  afi_t afi;
+  safi_t safi;
+  struct bgp_node *rn;
+  struct bgp_node *rm;
+  struct bgp_table *table;
+  struct bgp_static *bgp_static;
+
+  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+      for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn))
+	if (rn->info != NULL)
+	  {      
+	    if (safi == SAFI_MPLS_VPN)
+	      {
+		table = rn->info;
+
+		for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm))
+		  {
+		    bgp_static = rn->info;
+		    bgp_static_withdraw_vpnv4 (bgp, &rm->p,
+					       AFI_IP, SAFI_MPLS_VPN,
+					       (struct prefix_rd *)&rn->p,
+					       bgp_static->tag);
+		    bgp_static_free (bgp_static);
+		    rn->info = NULL;
+		    bgp_unlock_node (rn);
+		  }
+	      }
+	    else
+	      {
+		bgp_static = rn->info;
+		bgp_static_withdraw (bgp, &rn->p, afi, safi);
+		bgp_static_free (bgp_static);
+		rn->info = NULL;
+		bgp_unlock_node (rn);
+	      }
+	  }
+}
+
+int
+bgp_static_set_vpnv4 (struct vty *vty, char *ip_str, char *rd_str,
+		      char *tag_str)
+{
+  int ret;
+  struct prefix p;
+  struct prefix_rd prd;
+  struct bgp *bgp;
+  struct bgp_node *prn;
+  struct bgp_node *rn;
+  struct bgp_table *table;
+  struct bgp_static *bgp_static;
+  u_char tag[3];
+
+  bgp = vty->index;
+
+  ret = str2prefix (ip_str, &p);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed prefix%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  apply_mask (&p);
+
+  ret = str2prefix_rd (rd_str, &prd);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed rd%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ret = str2tag (tag_str, tag);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed tag%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  prn = bgp_node_get (bgp->route[AFI_IP][SAFI_MPLS_VPN],
+			(struct prefix *)&prd);
+  if (prn->info == NULL)
+    prn->info = bgp_table_init ();
+  else
+    bgp_unlock_node (prn);
+  table = prn->info;
+
+  rn = bgp_node_get (table, &p);
+
+  if (rn->info)
+    {
+      vty_out (vty, "%% Same network configuration exists%s", VTY_NEWLINE);
+      bgp_unlock_node (rn);
+    }
+  else
+    {
+      /* New configuration. */
+      bgp_static = bgp_static_new ();
+      bgp_static->valid = 1;
+      memcpy (bgp_static->tag, tag, 3);
+      rn->info = bgp_static;
+
+      bgp_static_update_vpnv4 (bgp, &p, AFI_IP, SAFI_MPLS_VPN, &prd, tag);
+    }
+
+  return CMD_SUCCESS;
+}
+
+/* Configure static BGP network. */
+int
+bgp_static_unset_vpnv4 (struct vty *vty, char *ip_str, char *rd_str,
+			char *tag_str)
+{
+  int ret;
+  struct bgp *bgp;
+  struct prefix p;
+  struct prefix_rd prd;
+  struct bgp_node *prn;
+  struct bgp_node *rn;
+  struct bgp_table *table;
+  struct bgp_static *bgp_static;
+  u_char tag[3];
+
+  bgp = vty->index;
+
+  /* Convert IP prefix string to struct prefix. */
+  ret = str2prefix (ip_str, &p);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed prefix%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  apply_mask (&p);
+
+  ret = str2prefix_rd (rd_str, &prd);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed rd%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ret = str2tag (tag_str, tag);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed tag%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  prn = bgp_node_get (bgp->route[AFI_IP][SAFI_MPLS_VPN],
+			(struct prefix *)&prd);
+  if (prn->info == NULL)
+    prn->info = bgp_table_init ();
+  else
+    bgp_unlock_node (prn);
+  table = prn->info;
+
+  rn = bgp_node_lookup (table, &p);
+
+  if (rn)
+    {
+      bgp_static_withdraw_vpnv4 (bgp, &p, AFI_IP, SAFI_MPLS_VPN, &prd, tag);
+
+      bgp_static = rn->info;
+      bgp_static_free (bgp_static);
+      rn->info = NULL;
+      bgp_unlock_node (rn);
+      bgp_unlock_node (rn);
+    }
+  else
+    vty_out (vty, "%% Can't find the route%s", VTY_NEWLINE);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (bgp_network,
+       bgp_network_cmd,
+       "network A.B.C.D/M",
+       "Specify a network to announce via BGP\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
+{
+  return bgp_static_set (vty, vty->index, argv[0],
+			 AFI_IP, bgp_node_safi (vty), NULL, 0);
+}
+
+DEFUN (bgp_network_route_map,
+       bgp_network_route_map_cmd,
+       "network A.B.C.D/M route-map WORD",
+       "Specify a network to announce via BGP\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+       "Route-map to modify the attributes\n"
+       "Name of the route map\n")
+{
+  return bgp_static_set (vty, vty->index, argv[0],
+			 AFI_IP, bgp_node_safi (vty), argv[1], 0);
+}
+
+DEFUN (bgp_network_backdoor,
+       bgp_network_backdoor_cmd,
+       "network A.B.C.D/M backdoor",
+       "Specify a network to announce via BGP\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+       "Specify a BGP backdoor route\n")
+{
+  return bgp_static_set (vty, vty->index, argv[0], AFI_IP, SAFI_UNICAST, NULL, 1);
+}
+
+DEFUN (bgp_network_mask,
+       bgp_network_mask_cmd,
+       "network A.B.C.D mask A.B.C.D",
+       "Specify a network to announce via BGP\n"
+       "Network number\n"
+       "Network mask\n"
+       "Network mask\n")
+{
+  int ret;
+  char prefix_str[BUFSIZ];
+
+  ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
+  if (! ret)
+    {
+      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_static_set (vty, vty->index, prefix_str,
+			 AFI_IP, bgp_node_safi (vty), NULL, 0);
+}
+
+DEFUN (bgp_network_mask_route_map,
+       bgp_network_mask_route_map_cmd,
+       "network A.B.C.D mask A.B.C.D route-map WORD",
+       "Specify a network to announce via BGP\n"
+       "Network number\n"
+       "Network mask\n"
+       "Network mask\n"
+       "Route-map to modify the attributes\n"
+       "Name of the route map\n")
+{
+  int ret;
+  char prefix_str[BUFSIZ];
+
+  ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
+  if (! ret)
+    {
+      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_static_set (vty, vty->index, prefix_str,
+			 AFI_IP, bgp_node_safi (vty), argv[2], 0);
+}
+
+DEFUN (bgp_network_mask_backdoor,
+       bgp_network_mask_backdoor_cmd,
+       "network A.B.C.D mask A.B.C.D backdoor",
+       "Specify a network to announce via BGP\n"
+       "Network number\n"
+       "Network mask\n"
+       "Network mask\n"
+       "Specify a BGP backdoor route\n")
+{
+  int ret;
+  char prefix_str[BUFSIZ];
+
+  ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
+  if (! ret)
+    {
+      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_static_set (vty, vty->index, prefix_str, AFI_IP, SAFI_UNICAST, NULL, 1);
+}
+
+DEFUN (bgp_network_mask_natural,
+       bgp_network_mask_natural_cmd,
+       "network A.B.C.D",
+       "Specify a network to announce via BGP\n"
+       "Network number\n")
+{
+  int ret;
+  char prefix_str[BUFSIZ];
+
+  ret = netmask_str2prefix_str (argv[0], NULL, prefix_str);
+  if (! ret)
+    {
+      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_static_set (vty, vty->index, prefix_str,
+			 AFI_IP, bgp_node_safi (vty), NULL, 0);
+}
+
+DEFUN (bgp_network_mask_natural_route_map,
+       bgp_network_mask_natural_route_map_cmd,
+       "network A.B.C.D route-map WORD",
+       "Specify a network to announce via BGP\n"
+       "Network number\n"
+       "Route-map to modify the attributes\n"
+       "Name of the route map\n")
+{
+  int ret;
+  char prefix_str[BUFSIZ];
+
+  ret = netmask_str2prefix_str (argv[0], NULL, prefix_str);
+  if (! ret)
+    {
+      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_static_set (vty, vty->index, prefix_str,
+			 AFI_IP, bgp_node_safi (vty), argv[1], 0);
+}
+
+DEFUN (bgp_network_mask_natural_backdoor,
+       bgp_network_mask_natural_backdoor_cmd,
+       "network A.B.C.D backdoor",
+       "Specify a network to announce via BGP\n"
+       "Network number\n"
+       "Specify a BGP backdoor route\n")
+{
+  int ret;
+  char prefix_str[BUFSIZ];
+
+  ret = netmask_str2prefix_str (argv[0], NULL, prefix_str);
+  if (! ret)
+    {
+      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_static_set (vty, vty->index, prefix_str, AFI_IP, SAFI_UNICAST, NULL, 1);
+}
+
+DEFUN (no_bgp_network,
+       no_bgp_network_cmd,
+       "no network A.B.C.D/M",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
+{
+  return bgp_static_unset (vty, vty->index, argv[0], AFI_IP, 
+			   bgp_node_safi (vty));
+}
+
+ALIAS (no_bgp_network,
+       no_bgp_network_route_map_cmd,
+       "no network A.B.C.D/M route-map WORD",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+       "Route-map to modify the attributes\n"
+       "Name of the route map\n")
+
+ALIAS (no_bgp_network,
+       no_bgp_network_backdoor_cmd,
+       "no network A.B.C.D/M backdoor",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+       "Specify a BGP backdoor route\n")
+
+DEFUN (no_bgp_network_mask,
+       no_bgp_network_mask_cmd,
+       "no network A.B.C.D mask A.B.C.D",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "Network number\n"
+       "Network mask\n"
+       "Network mask\n")
+{
+  int ret;
+  char prefix_str[BUFSIZ];
+
+  ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
+  if (! ret)
+    {
+      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_static_unset (vty, vty->index, prefix_str, AFI_IP, 
+			   bgp_node_safi (vty));
+}
+
+ALIAS (no_bgp_network_mask,
+       no_bgp_network_mask_route_map_cmd,
+       "no network A.B.C.D mask A.B.C.D route-map WORD",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "Network number\n"
+       "Network mask\n"
+       "Network mask\n"
+       "Route-map to modify the attributes\n"
+       "Name of the route map\n")
+
+ALIAS (no_bgp_network_mask,
+       no_bgp_network_mask_backdoor_cmd,
+       "no network A.B.C.D mask A.B.C.D backdoor",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "Network number\n"
+       "Network mask\n"
+       "Network mask\n"
+       "Specify a BGP backdoor route\n")
+
+DEFUN (no_bgp_network_mask_natural,
+       no_bgp_network_mask_natural_cmd,
+       "no network A.B.C.D",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "Network number\n")
+{
+  int ret;
+  char prefix_str[BUFSIZ];
+
+  ret = netmask_str2prefix_str (argv[0], NULL, prefix_str);
+  if (! ret)
+    {
+      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_static_unset (vty, vty->index, prefix_str, AFI_IP, 
+			   bgp_node_safi (vty));
+}
+
+ALIAS (no_bgp_network_mask_natural,
+       no_bgp_network_mask_natural_route_map_cmd,
+       "no network A.B.C.D route-map WORD",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "Network number\n"
+       "Route-map to modify the attributes\n"
+       "Name of the route map\n")
+
+ALIAS (no_bgp_network_mask_natural,
+       no_bgp_network_mask_natural_backdoor_cmd,
+       "no network A.B.C.D backdoor",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "Network number\n"
+       "Specify a BGP backdoor route\n")
+
+#ifdef HAVE_IPV6
+DEFUN (ipv6_bgp_network,
+       ipv6_bgp_network_cmd,
+       "network X:X::X:X/M",
+       "Specify a network to announce via BGP\n"
+       "IPv6 prefix <network>/<length>\n")
+{
+  return bgp_static_set (vty, vty->index, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0);
+}
+
+DEFUN (ipv6_bgp_network_route_map,
+       ipv6_bgp_network_route_map_cmd,
+       "network X:X::X:X/M route-map WORD",
+       "Specify a network to announce via BGP\n"
+       "IPv6 prefix <network>/<length>\n"
+       "Route-map to modify the attributes\n"
+       "Name of the route map\n")
+{
+  return bgp_static_set (vty, vty->index, argv[0], AFI_IP6,
+			 bgp_node_safi (vty), argv[1], 0);
+}
+
+DEFUN (no_ipv6_bgp_network,
+       no_ipv6_bgp_network_cmd,
+       "no network X:X::X:X/M",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "IPv6 prefix <network>/<length>\n")
+{
+  return bgp_static_unset (vty, vty->index, argv[0], AFI_IP6, SAFI_UNICAST);
+}
+
+ALIAS (no_ipv6_bgp_network,
+       no_ipv6_bgp_network_route_map_cmd,
+       "no network X:X::X:X/M route-map WORD",
+       NO_STR
+       "Specify a network to announce via BGP\n"
+       "IPv6 prefix <network>/<length>\n"
+       "Route-map to modify the attributes\n"
+       "Name of the route map\n")
+
+ALIAS (ipv6_bgp_network,
+       old_ipv6_bgp_network_cmd,
+       "ipv6 bgp network X:X::X:X/M",
+       IPV6_STR
+       BGP_STR
+       "Specify a network to announce via BGP\n"
+       "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
+
+ALIAS (no_ipv6_bgp_network,
+       old_no_ipv6_bgp_network_cmd,
+       "no ipv6 bgp network X:X::X:X/M",
+       NO_STR
+       IPV6_STR
+       BGP_STR
+       "Specify a network to announce via BGP\n"
+       "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
+#endif /* HAVE_IPV6 */
+
+/* Aggreagete address:
+
+  advertise-map  Set condition to advertise attribute
+  as-set         Generate AS set path information
+  attribute-map  Set attributes of aggregate
+  route-map      Set parameters of aggregate
+  summary-only   Filter more specific routes from updates
+  suppress-map   Conditionally filter more specific routes from updates
+  <cr>
+ */
+struct bgp_aggregate
+{
+  /* Summary-only flag. */
+  u_char summary_only;
+
+  /* AS set generation. */
+  u_char as_set;
+
+  /* Route-map for aggregated route. */
+  struct route_map *map;
+
+  /* Suppress-count. */
+  unsigned long count;
+
+  /* SAFI configuration. */
+  safi_t safi;
+};
+
+struct bgp_aggregate *
+bgp_aggregate_new ()
+{
+  struct bgp_aggregate *new;
+  new = XMALLOC (MTYPE_BGP_AGGREGATE, sizeof (struct bgp_aggregate));
+  memset (new, 0, sizeof (struct bgp_aggregate));
+  return new;
+}
+
+void
+bgp_aggregate_free (struct bgp_aggregate *aggregate)
+{
+  XFREE (MTYPE_BGP_AGGREGATE, aggregate);
+}     
+
+void
+bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew,
+		     afi_t afi, safi_t safi, struct bgp_info *del, 
+		     struct bgp_aggregate *aggregate)
+{
+  struct bgp_table *table;
+  struct bgp_node *top;
+  struct bgp_node *rn;
+  u_char origin;
+  struct aspath *aspath = NULL;
+  struct aspath *asmerge = NULL;
+  struct community *community = NULL;
+  struct community *commerge = NULL;
+  struct in_addr nexthop;
+  u_int32_t med = 0;
+  struct bgp_info *ri;
+  struct bgp_info *new;
+  int first = 1;
+  unsigned long match = 0;
+
+  /* Record adding route's nexthop and med. */
+  if (rinew)
+    {
+      nexthop = rinew->attr->nexthop;
+      med = rinew->attr->med;
+    }
+
+  /* ORIGIN attribute: If at least one route among routes that are
+     aggregated has ORIGIN with the value INCOMPLETE, then the
+     aggregated route must have the ORIGIN attribute with the value
+     INCOMPLETE. Otherwise, if at least one route among routes that
+     are aggregated has ORIGIN with the value EGP, then the aggregated
+     route must have the origin attribute with the value EGP. In all
+     other case the value of the ORIGIN attribute of the aggregated
+     route is INTERNAL. */
+  origin = BGP_ORIGIN_IGP;
+
+  table = bgp->rib[afi][safi];
+
+  top = bgp_node_get (table, p);
+  for (rn = bgp_node_get (table, p); rn; rn = bgp_route_next_until (rn, top))
+    if (rn->p.prefixlen > p->prefixlen)
+      {
+	match = 0;
+
+	for (ri = rn->info; ri; ri = ri->next)
+	  {
+	    if (BGP_INFO_HOLDDOWN (ri))
+	      continue;
+
+	    if (del && ri == del)
+	      continue;
+
+	    if (! rinew && first)
+	      {
+		nexthop = ri->attr->nexthop;
+		med = ri->attr->med;
+		first = 0;
+	      }
+
+#ifdef AGGREGATE_NEXTHOP_CHECK
+	    if (! IPV4_ADDR_SAME (&ri->attr->nexthop, &nexthop)
+		|| ri->attr->med != med)
+	      {
+		if (aspath)
+		  aspath_free (aspath);
+		if (community)
+		  community_free (community);
+		bgp_unlock_node (rn);
+		bgp_unlock_node (top);
+		return;
+	      }
+#endif /* AGGREGATE_NEXTHOP_CHECK */
+
+	    if (ri->sub_type != BGP_ROUTE_AGGREGATE)
+	      {
+		if (aggregate->summary_only)
+		  {
+		    ri->suppress++;
+		    SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+		    match++;
+		  }
+
+		aggregate->count++;
+
+		if (aggregate->as_set)
+		  {
+		    if (origin < ri->attr->origin)
+		      origin = ri->attr->origin;
+
+		    if (aspath)
+		      {
+			asmerge = aspath_aggregate (aspath, ri->attr->aspath);
+			aspath_free (aspath);
+			aspath = asmerge;
+		      }
+		    else
+		      aspath = aspath_dup (ri->attr->aspath);
+
+		    if (ri->attr->community)
+		      {
+			if (community)
+			  {
+			    commerge = community_merge (community,
+							ri->attr->community);
+			    community = community_uniq_sort (commerge);
+			    community_free (commerge);
+			  }
+			else
+			  community = community_dup (ri->attr->community);
+		      }
+		  }
+	      }
+	  }
+	if (match)
+	  bgp_process (bgp, rn, afi, safi);
+      }
+  bgp_unlock_node (top);
+
+  if (rinew)
+    {
+      aggregate->count++;
+      
+      if (aggregate->summary_only)
+	rinew->suppress++;
+
+      if (aggregate->as_set)
+	{
+	  if (origin < rinew->attr->origin)
+	    origin = rinew->attr->origin;
+
+	  if (aspath)
+	    {
+	      asmerge = aspath_aggregate (aspath, rinew->attr->aspath);
+	      aspath_free (aspath);
+	      aspath = asmerge;
+	    }
+	  else
+	    aspath = aspath_dup (rinew->attr->aspath);
+
+	  if (rinew->attr->community)
+	    {
+	      if (community)
+		{
+		  commerge = community_merge (community,
+					      rinew->attr->community);
+		  community = community_uniq_sort (commerge);
+		  community_free (commerge);
+		}
+	      else
+		community = community_dup (rinew->attr->community);
+	    }
+	}
+    }
+
+  if (aggregate->count > 0)
+    {
+      rn = bgp_node_get (table, p);
+      new = bgp_info_new ();
+      new->type = ZEBRA_ROUTE_BGP;
+      new->sub_type = BGP_ROUTE_AGGREGATE;
+      new->peer = bgp->peer_self;
+      SET_FLAG (new->flags, BGP_INFO_VALID);
+      new->attr = bgp_attr_aggregate_intern (bgp, origin, aspath, community, aggregate->as_set);
+      new->uptime = time (NULL);
+
+      bgp_info_add (rn, new);
+      bgp_process (bgp, rn, afi, safi);
+    }
+  else
+    {
+      if (aspath)
+	aspath_free (aspath);
+      if (community)
+	community_free (community);
+    }
+}
+
+void bgp_aggregate_delete (struct bgp *, struct prefix *, afi_t, safi_t,
+			   struct bgp_aggregate *);
+
+void
+bgp_aggregate_increment (struct bgp *bgp, struct prefix *p,
+			 struct bgp_info *ri, afi_t afi, safi_t safi)
+{
+  struct bgp_node *child;
+  struct bgp_node *rn;
+  struct bgp_aggregate *aggregate;
+
+  /* MPLS-VPN aggregation is not yet supported. */
+  if (safi == SAFI_MPLS_VPN)
+    return;
+
+  if (p->prefixlen == 0)
+    return;
+
+  if (BGP_INFO_HOLDDOWN (ri))
+    return;
+
+  child = bgp_node_get (bgp->aggregate[afi][safi], p);
+
+  /* Aggregate address configuration check. */
+  for (rn = child; rn; rn = rn->parent)
+    if ((aggregate = rn->info) != NULL && rn->p.prefixlen < p->prefixlen)
+      {
+	bgp_aggregate_delete (bgp, &rn->p, afi, safi, aggregate);
+	bgp_aggregate_route (bgp, &rn->p, ri, safi, safi, NULL, aggregate);
+      }
+  bgp_unlock_node (child);
+}
+
+void
+bgp_aggregate_decrement (struct bgp *bgp, struct prefix *p, 
+			 struct bgp_info *del, afi_t afi, safi_t safi)
+{
+  struct bgp_node *child;
+  struct bgp_node *rn;
+  struct bgp_aggregate *aggregate;
+
+  /* MPLS-VPN aggregation is not yet supported. */
+  if (safi == SAFI_MPLS_VPN)
+    return;
+
+  if (p->prefixlen == 0)
+    return;
+
+  child = bgp_node_get (bgp->aggregate[afi][safi], p);
+
+  /* Aggregate address configuration check. */
+  for (rn = child; rn; rn = rn->parent)
+    if ((aggregate = rn->info) != NULL && rn->p.prefixlen < p->prefixlen)
+      {
+	bgp_aggregate_delete (bgp, &rn->p, afi, safi, aggregate);
+	bgp_aggregate_route (bgp, &rn->p, NULL, safi, safi, del, aggregate);
+      }
+  bgp_unlock_node (child);
+}
+
+void
+bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi,
+		   struct bgp_aggregate *aggregate)
+{
+  struct bgp_table *table;
+  struct bgp_node *top;
+  struct bgp_node *rn;
+  struct bgp_info *new;
+  struct bgp_info *ri;
+  unsigned long match;
+  u_char origin = BGP_ORIGIN_IGP;
+  struct aspath *aspath = NULL;
+  struct aspath *asmerge = NULL;
+  struct community *community = NULL;
+  struct community *commerge = NULL;
+
+  table = bgp->rib[afi][safi];
+
+  /* Sanity check. */
+  if (afi == AFI_IP && p->prefixlen == IPV4_MAX_BITLEN)
+    return;
+  if (afi == AFI_IP6 && p->prefixlen == IPV6_MAX_BITLEN)
+    return;
+    
+  /* If routes exists below this node, generate aggregate routes. */
+  top = bgp_node_get (table, p);
+  for (rn = bgp_node_get (table, p); rn; rn = bgp_route_next_until (rn, top))
+    if (rn->p.prefixlen > p->prefixlen)
+      {
+	match = 0;
+
+	for (ri = rn->info; ri; ri = ri->next)
+	  {
+	    if (BGP_INFO_HOLDDOWN (ri))
+	      continue;
+
+	    if (ri->sub_type != BGP_ROUTE_AGGREGATE)
+	      {
+		/* summary-only aggregate route suppress aggregated
+		   route announcement.  */
+		if (aggregate->summary_only)
+		  {
+		    ri->suppress++;
+		    SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+		    match++;
+		  }
+		/* as-set aggregate route generate origin, as path,
+		   community aggregation.  */
+		if (aggregate->as_set)
+		  {
+		    if (origin < ri->attr->origin)
+		      origin = ri->attr->origin;
+
+		    if (aspath)
+		      {
+			asmerge = aspath_aggregate (aspath, ri->attr->aspath);
+			aspath_free (aspath);
+			aspath = asmerge;
+		      }
+		    else
+		      aspath = aspath_dup (ri->attr->aspath);
+
+		    if (ri->attr->community)
+		      {
+			if (community)
+			  {
+			    commerge = community_merge (community,
+							ri->attr->community);
+			    community = community_uniq_sort (commerge);
+			    community_free (commerge);
+			  }
+			else
+			  community = community_dup (ri->attr->community);
+		      }
+		  }
+		aggregate->count++;
+	      }
+	  }
+	
+	/* If this node is suppressed, process the change. */
+	if (match)
+	  bgp_process (bgp, rn, afi, safi);
+      }
+  bgp_unlock_node (top);
+
+  /* Add aggregate route to BGP table. */
+  if (aggregate->count)
+    {
+      rn = bgp_node_get (table, p);
+
+      new = bgp_info_new ();
+      new->type = ZEBRA_ROUTE_BGP;
+      new->sub_type = BGP_ROUTE_AGGREGATE;
+      new->peer = bgp->peer_self;
+      SET_FLAG (new->flags, BGP_INFO_VALID);
+      new->attr = bgp_attr_aggregate_intern (bgp, origin, aspath, community, aggregate->as_set);
+      new->uptime = time (NULL);
+
+      bgp_info_add (rn, new);
+
+      /* Process change. */
+      bgp_process (bgp, rn, afi, safi);
+    }
+}
+
+void
+bgp_aggregate_delete (struct bgp *bgp, struct prefix *p, afi_t afi, 
+		      safi_t safi, struct bgp_aggregate *aggregate)
+{
+  struct bgp_table *table;
+  struct bgp_node *top;
+  struct bgp_node *rn;
+  struct bgp_info *ri;
+  unsigned long match;
+
+  table = bgp->rib[afi][safi];
+
+  if (afi == AFI_IP && p->prefixlen == IPV4_MAX_BITLEN)
+    return;
+  if (afi == AFI_IP6 && p->prefixlen == IPV6_MAX_BITLEN)
+    return;
+
+  /* If routes exists below this node, generate aggregate routes. */
+  top = bgp_node_get (table, p);
+  for (rn = bgp_node_get (table, p); rn; rn = bgp_route_next_until (rn, top))
+    if (rn->p.prefixlen > p->prefixlen)
+      {
+	match = 0;
+
+	for (ri = rn->info; ri; ri = ri->next)
+	  {
+	    if (BGP_INFO_HOLDDOWN (ri))
+	      continue;
+
+	    if (ri->sub_type != BGP_ROUTE_AGGREGATE)
+	      {
+		if (aggregate->summary_only)
+		  {
+		    ri->suppress--;
+
+		    if (ri->suppress == 0)
+		      {
+			SET_FLAG (ri->flags, BGP_INFO_ATTR_CHANGED);
+			match++;
+		      }
+		  }
+		aggregate->count--;
+	      }
+	  }
+
+	/* If this node is suppressed, process the change. */
+	if (match)
+	  bgp_process (bgp, rn, afi, safi);
+      }
+  bgp_unlock_node (top);
+
+  /* Delete aggregate route from BGP table. */
+  rn = bgp_node_get (table, p);
+
+  for (ri = rn->info; ri; ri = ri->next)
+    if (ri->peer == bgp->peer_self 
+	&& ri->type == ZEBRA_ROUTE_BGP
+	&& ri->sub_type == BGP_ROUTE_AGGREGATE)
+      break;
+
+  /* Withdraw static BGP route from routing table. */
+  if (ri)
+    {
+      UNSET_FLAG (ri->flags, BGP_INFO_VALID);
+      bgp_process (bgp, rn, afi, safi);
+      bgp_info_delete (rn, ri);
+      bgp_info_free (ri);
+      bgp_unlock_node (rn);
+    }
+
+  /* Unlock bgp_node_lookup. */
+  bgp_unlock_node (rn);
+}
+
+/* Aggregate route attribute. */
+#define AGGREGATE_SUMMARY_ONLY 1
+#define AGGREGATE_AS_SET       1
+
+int
+bgp_aggregate_set (struct vty *vty, char *prefix_str, afi_t afi, safi_t safi,
+		   u_char summary_only, u_char as_set)
+{
+  int ret;
+  struct prefix p;
+  struct bgp_node *rn;
+  struct bgp *bgp;
+  struct bgp_aggregate *aggregate;
+
+  /* Convert string to prefix structure. */
+  ret = str2prefix (prefix_str, &p);
+  if (!ret)
+    {
+      vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  apply_mask (&p);
+
+  /* Get BGP structure. */
+  bgp = vty->index;
+
+  /* Old configuration check. */
+  rn = bgp_node_get (bgp->aggregate[afi][safi], &p);
+
+  if (rn->info)
+    {
+      vty_out (vty, "There is already same aggregate network.%s", VTY_NEWLINE);
+      bgp_unlock_node (rn);
+      return CMD_WARNING;
+    }
+
+  /* Make aggregate address structure. */
+  aggregate = bgp_aggregate_new ();
+  aggregate->summary_only = summary_only;
+  aggregate->as_set = as_set;
+  aggregate->safi = safi;
+  rn->info = aggregate;
+
+  /* Aggregate address insert into BGP routing table. */
+  if (safi & SAFI_UNICAST)
+    bgp_aggregate_add (bgp, &p, afi, SAFI_UNICAST, aggregate);
+  if (safi & SAFI_MULTICAST)
+    bgp_aggregate_add (bgp, &p, afi, SAFI_MULTICAST, aggregate);
+
+  return CMD_SUCCESS;
+}
+
+int
+bgp_aggregate_unset (struct vty *vty, char *prefix_str, afi_t afi, safi_t safi)
+{
+  int ret;
+  struct prefix p;
+  struct bgp_node *rn;
+  struct bgp *bgp;
+  struct bgp_aggregate *aggregate;
+
+  /* Convert string to prefix structure. */
+  ret = str2prefix (prefix_str, &p);
+  if (!ret)
+    {
+      vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  apply_mask (&p);
+
+  /* Get BGP structure. */
+  bgp = vty->index;
+
+  /* Old configuration check. */
+  rn = bgp_node_lookup (bgp->aggregate[afi][safi], &p);
+  if (! rn)
+    {
+      vty_out (vty, "%% There is no aggregate-address configuration.%s",
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  aggregate = rn->info;
+  if (aggregate->safi & SAFI_UNICAST)
+    bgp_aggregate_delete (bgp, &p, afi, SAFI_UNICAST, aggregate);
+  if (aggregate->safi & SAFI_MULTICAST)
+    bgp_aggregate_delete (bgp, &p, afi, SAFI_MULTICAST, aggregate);
+
+  /* Unlock aggregate address configuration. */
+  rn->info = NULL;
+  bgp_aggregate_free (aggregate);
+  bgp_unlock_node (rn);
+  bgp_unlock_node (rn);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (aggregate_address,
+       aggregate_address_cmd,
+       "aggregate-address A.B.C.D/M",
+       "Configure BGP aggregate entries\n"
+       "Aggregate prefix\n")
+{
+  return bgp_aggregate_set (vty, argv[0], AFI_IP, bgp_node_safi (vty), 0, 0);
+}
+
+DEFUN (aggregate_address_mask,
+       aggregate_address_mask_cmd,
+       "aggregate-address A.B.C.D A.B.C.D",
+       "Configure BGP aggregate entries\n"
+       "Aggregate address\n"
+       "Aggregate mask\n")
+{
+  int ret;
+  char prefix_str[BUFSIZ];
+
+  ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
+
+  if (! ret)
+    {
+      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_aggregate_set (vty, prefix_str, AFI_IP, bgp_node_safi (vty),
+			    0, 0);
+}
+
+DEFUN (aggregate_address_summary_only,
+       aggregate_address_summary_only_cmd,
+       "aggregate-address A.B.C.D/M summary-only",
+       "Configure BGP aggregate entries\n"
+       "Aggregate prefix\n"
+       "Filter more specific routes from updates\n")
+{
+  return bgp_aggregate_set (vty, argv[0], AFI_IP, bgp_node_safi (vty),
+			    AGGREGATE_SUMMARY_ONLY, 0);
+}
+
+DEFUN (aggregate_address_mask_summary_only,
+       aggregate_address_mask_summary_only_cmd,
+       "aggregate-address A.B.C.D A.B.C.D summary-only",
+       "Configure BGP aggregate entries\n"
+       "Aggregate address\n"
+       "Aggregate mask\n"
+       "Filter more specific routes from updates\n")
+{
+  int ret;
+  char prefix_str[BUFSIZ];
+
+  ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
+
+  if (! ret)
+    {
+      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_aggregate_set (vty, prefix_str, AFI_IP, bgp_node_safi (vty),
+			    AGGREGATE_SUMMARY_ONLY, 0);
+}
+
+DEFUN (aggregate_address_as_set,
+       aggregate_address_as_set_cmd,
+       "aggregate-address A.B.C.D/M as-set",
+       "Configure BGP aggregate entries\n"
+       "Aggregate prefix\n"
+       "Generate AS set path information\n")
+{
+  return bgp_aggregate_set (vty, argv[0], AFI_IP, bgp_node_safi (vty),
+			    0, AGGREGATE_AS_SET);
+}
+
+DEFUN (aggregate_address_mask_as_set,
+       aggregate_address_mask_as_set_cmd,
+       "aggregate-address A.B.C.D A.B.C.D as-set",
+       "Configure BGP aggregate entries\n"
+       "Aggregate address\n"
+       "Aggregate mask\n"
+       "Generate AS set path information\n")
+{
+  int ret;
+  char prefix_str[BUFSIZ];
+
+  ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
+
+  if (! ret)
+    {
+      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_aggregate_set (vty, prefix_str, AFI_IP, bgp_node_safi (vty),
+			    0, AGGREGATE_AS_SET);
+}
+
+
+DEFUN (aggregate_address_as_set_summary,
+       aggregate_address_as_set_summary_cmd,
+       "aggregate-address A.B.C.D/M as-set summary-only",
+       "Configure BGP aggregate entries\n"
+       "Aggregate prefix\n"
+       "Generate AS set path information\n"
+       "Filter more specific routes from updates\n")
+{
+  return bgp_aggregate_set (vty, argv[0], AFI_IP, bgp_node_safi (vty),
+			    AGGREGATE_SUMMARY_ONLY, AGGREGATE_AS_SET);
+}
+
+ALIAS (aggregate_address_as_set_summary,
+       aggregate_address_summary_as_set_cmd,
+       "aggregate-address A.B.C.D/M summary-only as-set",
+       "Configure BGP aggregate entries\n"
+       "Aggregate prefix\n"
+       "Filter more specific routes from updates\n"
+       "Generate AS set path information\n")
+
+DEFUN (aggregate_address_mask_as_set_summary,
+       aggregate_address_mask_as_set_summary_cmd,
+       "aggregate-address A.B.C.D A.B.C.D as-set summary-only",
+       "Configure BGP aggregate entries\n"
+       "Aggregate address\n"
+       "Aggregate mask\n"
+       "Generate AS set path information\n"
+       "Filter more specific routes from updates\n")
+{
+  int ret;
+  char prefix_str[BUFSIZ];
+
+  ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
+
+  if (! ret)
+    {
+      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_aggregate_set (vty, prefix_str, AFI_IP, bgp_node_safi (vty),
+			    AGGREGATE_SUMMARY_ONLY, AGGREGATE_AS_SET);
+}
+
+ALIAS (aggregate_address_mask_as_set_summary,
+       aggregate_address_mask_summary_as_set_cmd,
+       "aggregate-address A.B.C.D A.B.C.D summary-only as-set",
+       "Configure BGP aggregate entries\n"
+       "Aggregate address\n"
+       "Aggregate mask\n"
+       "Filter more specific routes from updates\n"
+       "Generate AS set path information\n")
+
+DEFUN (no_aggregate_address,
+       no_aggregate_address_cmd,
+       "no aggregate-address A.B.C.D/M",
+       NO_STR
+       "Configure BGP aggregate entries\n"
+       "Aggregate prefix\n")
+{
+  return bgp_aggregate_unset (vty, argv[0], AFI_IP, bgp_node_safi (vty));
+}
+
+ALIAS (no_aggregate_address,
+       no_aggregate_address_summary_only_cmd,
+       "no aggregate-address A.B.C.D/M summary-only",
+       NO_STR
+       "Configure BGP aggregate entries\n"
+       "Aggregate prefix\n"
+       "Filter more specific routes from updates\n")
+
+ALIAS (no_aggregate_address,
+       no_aggregate_address_as_set_cmd,
+       "no aggregate-address A.B.C.D/M as-set",
+       NO_STR
+       "Configure BGP aggregate entries\n"
+       "Aggregate prefix\n"
+       "Generate AS set path information\n")
+
+ALIAS (no_aggregate_address,
+       no_aggregate_address_as_set_summary_cmd,
+       "no aggregate-address A.B.C.D/M as-set summary-only",
+       NO_STR
+       "Configure BGP aggregate entries\n"
+       "Aggregate prefix\n"
+       "Generate AS set path information\n"
+       "Filter more specific routes from updates\n")
+
+ALIAS (no_aggregate_address,
+       no_aggregate_address_summary_as_set_cmd,
+       "no aggregate-address A.B.C.D/M summary-only as-set",
+       NO_STR
+       "Configure BGP aggregate entries\n"
+       "Aggregate prefix\n"
+       "Filter more specific routes from updates\n"
+       "Generate AS set path information\n")
+
+DEFUN (no_aggregate_address_mask,
+       no_aggregate_address_mask_cmd,
+       "no aggregate-address A.B.C.D A.B.C.D",
+       NO_STR
+       "Configure BGP aggregate entries\n"
+       "Aggregate address\n"
+       "Aggregate mask\n")
+{
+  int ret;
+  char prefix_str[BUFSIZ];
+
+  ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
+
+  if (! ret)
+    {
+      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_aggregate_unset (vty, prefix_str, AFI_IP, bgp_node_safi (vty));
+}
+
+ALIAS (no_aggregate_address_mask,
+       no_aggregate_address_mask_summary_only_cmd,
+       "no aggregate-address A.B.C.D A.B.C.D summary-only",
+       NO_STR
+       "Configure BGP aggregate entries\n"
+       "Aggregate address\n"
+       "Aggregate mask\n"
+       "Filter more specific routes from updates\n")
+
+ALIAS (no_aggregate_address_mask,
+       no_aggregate_address_mask_as_set_cmd,
+       "no aggregate-address A.B.C.D A.B.C.D as-set",
+       NO_STR
+       "Configure BGP aggregate entries\n"
+       "Aggregate address\n"
+       "Aggregate mask\n"
+       "Generate AS set path information\n")
+
+ALIAS (no_aggregate_address_mask,
+       no_aggregate_address_mask_as_set_summary_cmd,
+       "no aggregate-address A.B.C.D A.B.C.D as-set summary-only",
+       NO_STR
+       "Configure BGP aggregate entries\n"
+       "Aggregate address\n"
+       "Aggregate mask\n"
+       "Generate AS set path information\n"
+       "Filter more specific routes from updates\n")
+
+ALIAS (no_aggregate_address_mask,
+       no_aggregate_address_mask_summary_as_set_cmd,
+       "no aggregate-address A.B.C.D A.B.C.D summary-only as-set",
+       NO_STR
+       "Configure BGP aggregate entries\n"
+       "Aggregate address\n"
+       "Aggregate mask\n"
+       "Filter more specific routes from updates\n"
+       "Generate AS set path information\n")
+
+#ifdef HAVE_IPV6
+DEFUN (ipv6_aggregate_address,
+       ipv6_aggregate_address_cmd,
+       "aggregate-address X:X::X:X/M",
+       "Configure BGP aggregate entries\n"
+       "Aggregate prefix\n")
+{
+  return bgp_aggregate_set (vty, argv[0], AFI_IP6, SAFI_UNICAST, 0, 0);
+}
+
+DEFUN (ipv6_aggregate_address_summary_only,
+       ipv6_aggregate_address_summary_only_cmd,
+       "aggregate-address X:X::X:X/M summary-only",
+       "Configure BGP aggregate entries\n"
+       "Aggregate prefix\n"
+       "Filter more specific routes from updates\n")
+{
+  return bgp_aggregate_set (vty, argv[0], AFI_IP6, SAFI_UNICAST, 
+			    AGGREGATE_SUMMARY_ONLY, 0);
+}
+
+DEFUN (no_ipv6_aggregate_address,
+       no_ipv6_aggregate_address_cmd,
+       "no aggregate-address X:X::X:X/M",
+       NO_STR
+       "Configure BGP aggregate entries\n"
+       "Aggregate prefix\n")
+{
+  return bgp_aggregate_unset (vty, argv[0], AFI_IP6, SAFI_UNICAST);
+}
+
+DEFUN (no_ipv6_aggregate_address_summary_only,
+       no_ipv6_aggregate_address_summary_only_cmd,
+       "no aggregate-address X:X::X:X/M summary-only",
+       NO_STR
+       "Configure BGP aggregate entries\n"
+       "Aggregate prefix\n"
+       "Filter more specific routes from updates\n")
+{
+  return bgp_aggregate_unset (vty, argv[0], AFI_IP6, SAFI_UNICAST);
+}
+
+ALIAS (ipv6_aggregate_address,
+       old_ipv6_aggregate_address_cmd,
+       "ipv6 bgp aggregate-address X:X::X:X/M",
+       IPV6_STR
+       BGP_STR
+       "Configure BGP aggregate entries\n"
+       "Aggregate prefix\n")
+
+ALIAS (ipv6_aggregate_address_summary_only,
+       old_ipv6_aggregate_address_summary_only_cmd,
+       "ipv6 bgp aggregate-address X:X::X:X/M summary-only",
+       IPV6_STR
+       BGP_STR
+       "Configure BGP aggregate entries\n"
+       "Aggregate prefix\n"
+       "Filter more specific routes from updates\n")
+
+ALIAS (no_ipv6_aggregate_address,
+       old_no_ipv6_aggregate_address_cmd,
+       "no ipv6 bgp aggregate-address X:X::X:X/M",
+       NO_STR
+       IPV6_STR
+       BGP_STR
+       "Configure BGP aggregate entries\n"
+       "Aggregate prefix\n")
+
+ALIAS (no_ipv6_aggregate_address_summary_only,
+       old_no_ipv6_aggregate_address_summary_only_cmd,
+       "no ipv6 bgp aggregate-address X:X::X:X/M summary-only",
+       NO_STR
+       IPV6_STR
+       BGP_STR
+       "Configure BGP aggregate entries\n"
+       "Aggregate prefix\n"
+       "Filter more specific routes from updates\n")
+#endif /* HAVE_IPV6 */
+
+/* Redistribute route treatment. */
+void
+bgp_redistribute_add (struct prefix *p, struct in_addr *nexthop,
+		      u_int32_t metric, u_char type)
+{
+  struct bgp *bgp;
+  struct listnode *nn;
+  struct bgp_info *new;
+  struct bgp_info *bi;
+  struct bgp_info info;
+  struct bgp_node *bn;
+  struct attr attr;
+  struct attr attr_new;
+  struct attr *new_attr;
+  afi_t afi;
+  int ret;
+
+  /* Make default attribute. */
+  bgp_attr_default_set (&attr, BGP_ORIGIN_INCOMPLETE);
+  if (nexthop)
+    attr.nexthop = *nexthop;
+
+  attr.med = metric;
+  attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
+
+  LIST_LOOP (bm->bgp, bgp, nn)
+    {
+      afi = family2afi (p->family);
+
+      if (bgp->redist[afi][type])
+	{
+	  /* Copy attribute for modification. */
+	  attr_new = attr;
+
+	  if (bgp->redist_metric_flag[afi][type])
+	    attr_new.med = bgp->redist_metric[afi][type];
+
+	  /* Apply route-map. */
+	  if (bgp->rmap[afi][type].map)
+	    {
+	      info.peer = bgp->peer_self;
+	      info.attr = &attr_new;
+
+	      ret = route_map_apply (bgp->rmap[afi][type].map, p, RMAP_BGP,
+				     &info);
+	      if (ret == RMAP_DENYMATCH)
+		{
+		  /* Free uninterned attribute. */
+		  bgp_attr_flush (&attr_new);
+
+		  /* Unintern original. */
+		  aspath_unintern (attr.aspath);
+		  bgp_redistribute_delete (p, type);
+		  return;
+		}
+	    }
+
+	  bn = bgp_afi_node_get (bgp, afi, SAFI_UNICAST, p, NULL);
+	  new_attr = bgp_attr_intern (&attr_new);
+ 
+ 	  for (bi = bn->info; bi; bi = bi->next)
+ 	    if (bi->peer == bgp->peer_self
+ 		&& bi->sub_type == BGP_ROUTE_REDISTRIBUTE)
+ 	      break;
+ 
+ 	  if (bi)
+ 	    {
+ 	      if (attrhash_cmp (bi->attr, new_attr))
+ 		{
+ 		  bgp_attr_unintern (new_attr);
+ 		  aspath_unintern (attr.aspath);
+ 		  bgp_unlock_node (bn);
+ 		  return;
+ 		}
+ 	      else
+ 		{
+ 		  /* The attribute is changed. */
+ 		  SET_FLAG (bi->flags, BGP_INFO_ATTR_CHANGED);
+ 
+ 		  /* Rewrite BGP route information. */
+ 		  bgp_aggregate_decrement (bgp, p, bi, afi, SAFI_UNICAST);
+ 		  bgp_attr_unintern (bi->attr);
+ 		  bi->attr = new_attr;
+ 		  bi->uptime = time (NULL);
+ 
+ 		  /* Process change. */
+ 		  bgp_aggregate_increment (bgp, p, bi, afi, SAFI_UNICAST);
+ 		  bgp_process (bgp, bn, afi, SAFI_UNICAST);
+ 		  bgp_unlock_node (bn);
+ 		  aspath_unintern (attr.aspath);
+ 		  return;
+ 		} 
+ 	    }
+
+	  new = bgp_info_new ();
+	  new->type = type;
+	  new->sub_type = BGP_ROUTE_REDISTRIBUTE;
+	  new->peer = bgp->peer_self;
+	  SET_FLAG (new->flags, BGP_INFO_VALID);
+	  new->attr = new_attr;
+	  new->uptime = time (NULL);
+
+	  bgp_aggregate_increment (bgp, p, new, afi, SAFI_UNICAST);
+	  bgp_info_add (bn, new);
+	  bgp_process (bgp, bn, afi, SAFI_UNICAST);
+	}
+    }
+
+  /* Unintern original. */
+  aspath_unintern (attr.aspath);
+}
+
+void
+bgp_redistribute_delete (struct prefix *p, u_char type)
+{
+  struct bgp *bgp;
+  struct listnode *nn;
+  afi_t afi;
+  struct bgp_node *rn;
+  struct bgp_info *ri;
+
+  LIST_LOOP (bm->bgp, bgp, nn)
+    {
+      afi = family2afi (p->family);
+
+      if (bgp->redist[afi][type])
+	{
+	  rn = bgp_afi_node_get (bgp, afi, SAFI_UNICAST, p, NULL);
+
+	  for (ri = rn->info; ri; ri = ri->next)
+	    if (ri->peer == bgp->peer_self
+		&& ri->type == type)
+	      break;
+
+	  if (ri)
+	    {
+	      bgp_aggregate_decrement (bgp, p, ri, afi, SAFI_UNICAST);
+	      UNSET_FLAG (ri->flags, BGP_INFO_VALID);
+	      bgp_process (bgp, rn, afi, SAFI_UNICAST);
+	      bgp_info_delete (rn, ri);
+	      bgp_info_free (ri);
+	      bgp_unlock_node (rn);
+	    }
+	  bgp_unlock_node (rn);
+	}
+    }
+}
+
+/* Withdraw specified route type's route. */
+void
+bgp_redistribute_withdraw (struct bgp *bgp, afi_t afi, int type)
+{
+  struct bgp_node *rn;
+  struct bgp_info *ri;
+  struct bgp_table *table;
+
+  table = bgp->rib[afi][SAFI_UNICAST];
+
+  for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
+    {
+      for (ri = rn->info; ri; ri = ri->next)
+	if (ri->peer == bgp->peer_self
+	    && ri->type == type)
+	  break;
+
+      if (ri)
+	{
+	  bgp_aggregate_decrement (bgp, &rn->p, ri, afi, SAFI_UNICAST);
+	  UNSET_FLAG (ri->flags, BGP_INFO_VALID);
+	  bgp_process (bgp, rn, afi, SAFI_UNICAST);
+	  bgp_info_delete (rn, ri);
+	  bgp_info_free (ri);
+	  bgp_unlock_node (rn);
+	}
+    }
+}
+
+/* Static function to display route. */
+void
+route_vty_out_route (struct prefix *p, struct vty *vty)
+{
+  int len;
+  u_int32_t destination; 
+  char buf[BUFSIZ];
+
+  if (p->family == AF_INET)
+    {
+      len = vty_out (vty, "%s", inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ));
+      destination = ntohl (p->u.prefix4.s_addr);
+
+      if ((IN_CLASSC (destination) && p->prefixlen == 24)
+	  || (IN_CLASSB (destination) && p->prefixlen == 16)
+	  || (IN_CLASSA (destination) && p->prefixlen == 8)
+	  || p->u.prefix4.s_addr == 0)
+	{
+	  /* When mask is natural, mask is not displayed. */
+	}
+      else
+	len += vty_out (vty, "/%d", p->prefixlen);
+    }
+  else
+    len = vty_out (vty, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
+		   p->prefixlen);
+
+  len = 17 - len;
+  if (len < 1)
+    vty_out (vty, "%s%*s", VTY_NEWLINE, 20, " ");
+  else
+    vty_out (vty, "%*s", len, " ");
+}
+
+/* Calculate line number of output data. */
+int
+vty_calc_line (struct vty *vty, unsigned long length)
+{
+  return vty->width ? (((vty->obuf->length - length) / vty->width) + 1) : 1;
+}
+
+enum bgp_display_type
+{
+  normal_list,
+};
+
+/* called from terminal list command */
+int
+route_vty_out (struct vty *vty, struct prefix *p,
+	       struct bgp_info *binfo, int display, safi_t safi)
+{
+  struct attr *attr;
+  unsigned long length = 0;
+
+  length = vty->obuf->length;
+
+  /* Route status display. */
+  if (binfo->suppress)
+    vty_out (vty, "s");
+  else if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
+    vty_out (vty, "*");
+  else
+    vty_out (vty, " ");
+
+  /* Selected */
+  if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
+    vty_out (vty, "h");
+  else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
+    vty_out (vty, "d");
+  else if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))
+    vty_out (vty, ">");
+  else
+    vty_out (vty, " ");
+
+  /* Internal route. */
+    if ((binfo->peer->as) && (binfo->peer->as == binfo->peer->local_as))
+      vty_out (vty, "i");
+    else
+      vty_out (vty, " ");
+  
+  /* print prefix and mask */
+  if (! display)
+    route_vty_out_route (p, vty);
+  else
+    vty_out (vty, "%*s", 17, " ");
+
+  /* Print attribute */
+  attr = binfo->attr;
+  if (attr) 
+    {
+      if (p->family == AF_INET)
+	{
+	  if (safi == SAFI_MPLS_VPN)
+	    vty_out (vty, "%-16s", inet_ntoa (attr->mp_nexthop_global_in));
+	  else
+	    vty_out (vty, "%-16s", inet_ntoa (attr->nexthop));
+	}
+#ifdef HAVE_IPV6      
+      else if (p->family == AF_INET6)
+	{
+	  int len;
+	  char buf[BUFSIZ];
+
+	  len = vty_out (vty, "%s", 
+			 inet_ntop (AF_INET6, &attr->mp_nexthop_global, buf, BUFSIZ));
+	  len = 16 - len;
+	  if (len < 1)
+	    vty_out (vty, "%s%*s", VTY_NEWLINE, 36, " ");
+	  else
+	    vty_out (vty, "%*s", len, " ");
+	}
+#endif /* HAVE_IPV6 */
+
+      if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
+	vty_out (vty, "%10d", attr->med);
+      else
+	vty_out (vty, "          ");
+
+      if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
+	vty_out (vty, "%7d", attr->local_pref);
+      else
+	vty_out (vty, "       ");
+
+      vty_out (vty, "%7u ",attr->weight);
+    
+    /* Print aspath */
+    if (attr->aspath)
+      aspath_print_vty (vty, attr->aspath);
+
+    /* Print origin */
+    if (strlen (attr->aspath->str) == 0)
+      vty_out (vty, "%s", bgp_origin_str[attr->origin]);
+    else
+      vty_out (vty, " %s", bgp_origin_str[attr->origin]);
+  }
+  vty_out (vty, "%s", VTY_NEWLINE);
+
+  return vty_calc_line (vty, length);
+}  
+
+/* called from terminal list command */
+void
+route_vty_out_tmp (struct vty *vty, struct prefix *p,
+		   struct attr *attr, safi_t safi)
+{
+  /* Route status display. */
+  vty_out (vty, "*");
+  vty_out (vty, ">");
+  vty_out (vty, " ");
+
+  /* print prefix and mask */
+  route_vty_out_route (p, vty);
+
+  /* Print attribute */
+  if (attr) 
+    {
+      if (p->family == AF_INET)
+	{
+	  if (safi == SAFI_MPLS_VPN)
+	    vty_out (vty, "%-16s", inet_ntoa (attr->mp_nexthop_global_in));
+	  else
+	    vty_out (vty, "%-16s", inet_ntoa (attr->nexthop));
+	}
+#ifdef HAVE_IPV6
+      else if (p->family == AF_INET6)
+        {
+          int len;
+          char buf[BUFSIZ];
+
+          len = vty_out (vty, "%s",
+                         inet_ntop (AF_INET6, &attr->mp_nexthop_global, buf, BUFSIZ));
+          len = 16 - len;
+          if (len < 1)
+            vty_out (vty, "%s%*s", VTY_NEWLINE, 36, " ");
+          else
+            vty_out (vty, "%*s", len, " ");
+        }
+#endif /* HAVE_IPV6 */
+
+      if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
+	vty_out (vty, "%10d", attr->med);
+      else
+	vty_out (vty, "          ");
+
+      if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
+	vty_out (vty, "%7d", attr->local_pref);
+      else
+	vty_out (vty, "       ");
+
+      vty_out (vty, "%7d ",attr->weight);
+    
+    /* Print aspath */
+    if (attr->aspath)
+      aspath_print_vty (vty, attr->aspath);
+
+    /* Print origin */
+    if (strlen (attr->aspath->str) == 0)
+      vty_out (vty, "%s", bgp_origin_str[attr->origin]);
+    else
+      vty_out (vty, " %s", bgp_origin_str[attr->origin]);
+  }
+
+  vty_out (vty, "%s", VTY_NEWLINE);
+}  
+
+int
+route_vty_out_tag (struct vty *vty, struct prefix *p,
+		   struct bgp_info *binfo, int display, safi_t safi)
+{
+  struct attr *attr;
+  unsigned long length = 0;
+  u_int32_t label = 0;
+
+  length = vty->obuf->length;
+
+  /* Route status display. */
+  if (binfo->suppress)
+    vty_out (vty, "s");
+  else if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
+    vty_out (vty, "*");
+  else
+    vty_out (vty, " ");
+
+  /* Selected */
+  if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
+    vty_out (vty, "h");
+  else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
+    vty_out (vty, "d");
+  else if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))
+    vty_out (vty, ">");
+  else
+    vty_out (vty, " ");
+
+  /* Internal route. */
+    if ((binfo->peer->as) && (binfo->peer->as == binfo->peer->local_as))
+      vty_out (vty, "i");
+    else
+      vty_out (vty, " ");
+
+  /* print prefix and mask */
+  if (! display)
+    route_vty_out_route (p, vty);
+  else
+    vty_out (vty, "%*s", 17, " ");
+
+  /* Print attribute */
+  attr = binfo->attr;
+  if (attr) 
+    {
+      if (p->family == AF_INET)
+	{
+	  if (safi == SAFI_MPLS_VPN)
+	    vty_out (vty, "%-16s", inet_ntoa (attr->mp_nexthop_global_in));
+	  else
+	    vty_out (vty, "%-16s", inet_ntoa (attr->nexthop));
+	}
+#ifdef HAVE_IPV6      
+      else if (p->family == AF_INET6)
+	{
+	  char buf[BUFSIZ];
+	  char buf1[BUFSIZ];
+	  if (attr->mp_nexthop_len == 16)
+	    vty_out (vty, "%s", 
+		     inet_ntop (AF_INET6, &attr->mp_nexthop_global, buf, BUFSIZ));
+	  else if (attr->mp_nexthop_len == 32)
+	    vty_out (vty, "%s(%s)",
+		     inet_ntop (AF_INET6, &attr->mp_nexthop_global, buf, BUFSIZ),
+		     inet_ntop (AF_INET6, &attr->mp_nexthop_local, buf1, BUFSIZ));
+	  
+	}
+#endif /* HAVE_IPV6 */
+    }
+
+  label = decode_label (binfo->tag);
+
+  vty_out (vty, "notag/%d", label);
+
+  vty_out (vty, "%s", VTY_NEWLINE);
+
+  return vty_calc_line (vty, length);
+}  
+
+/* dampening route */
+int
+damp_route_vty_out (struct vty *vty, struct prefix *p,
+		    struct bgp_info *binfo, int display, safi_t safi)
+{
+  struct attr *attr;
+  unsigned long length = 0;
+  int len;
+
+  length = vty->obuf->length;
+
+  /* Route status display. */
+  if (binfo->suppress)
+    vty_out (vty, "s");
+  else if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
+    vty_out (vty, "*");
+  else
+    vty_out (vty, " ");
+
+  /* Selected */
+  if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
+    vty_out (vty, "h");
+  else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
+    vty_out (vty, "d");
+  else if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))
+    vty_out (vty, ">");
+  else
+    vty_out (vty, " ");
+
+  vty_out (vty, " ");
+
+  /* print prefix and mask */
+  if (! display)
+    route_vty_out_route (p, vty);
+  else
+    vty_out (vty, "%*s", 17, " ");
+
+  len = vty_out (vty, "%s", binfo->peer->host);
+  len = 17 - len;
+  if (len < 1)
+    vty_out (vty, "%s%*s", VTY_NEWLINE, 34, " ");
+  else
+    vty_out (vty, "%*s", len, " ");
+
+  vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo));
+
+  /* Print attribute */
+  attr = binfo->attr;
+  if (attr)
+    {
+      /* Print aspath */
+      if (attr->aspath)
+	aspath_print_vty (vty, attr->aspath);
+
+      /* Print origin */
+      if (strlen (attr->aspath->str) == 0)
+	vty_out (vty, "%s", bgp_origin_str[attr->origin]);
+      else
+	vty_out (vty, " %s", bgp_origin_str[attr->origin]);
+    }
+  vty_out (vty, "%s", VTY_NEWLINE);
+
+  return vty_calc_line (vty, length);
+}
+
+#define BGP_UPTIME_LEN 25
+
+/* flap route */
+int
+flap_route_vty_out (struct vty *vty, struct prefix *p,
+		    struct bgp_info *binfo, int display, safi_t safi)
+{
+  struct attr *attr;
+  struct bgp_damp_info *bdi;
+  unsigned long length = 0;
+  char timebuf[BGP_UPTIME_LEN];
+  int len;
+
+  length = vty->obuf->length;
+  bdi = binfo->damp_info;
+
+  /* Route status display. */
+  if (binfo->suppress)
+    vty_out (vty, "s");
+  else if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
+    vty_out (vty, "*");
+  else
+    vty_out (vty, " ");
+
+  /* Selected */
+  if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
+    vty_out (vty, "h");
+  else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
+    vty_out (vty, "d");
+  else if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))
+    vty_out (vty, ">");
+  else
+    vty_out (vty, " ");
+
+  vty_out (vty, " ");
+
+  /* print prefix and mask */
+  if (! display)
+    route_vty_out_route (p, vty);
+  else
+    vty_out (vty, "%*s", 17, " ");
+
+  len = vty_out (vty, "%s", binfo->peer->host);
+  len = 16 - len;
+  if (len < 1)
+    vty_out (vty, "%s%*s", VTY_NEWLINE, 33, " ");
+  else
+    vty_out (vty, "%*s", len, " ");
+
+  len = vty_out (vty, "%d", bdi->flap);
+  len = 5 - len;
+  if (len < 1)
+    vty_out (vty, " ");
+  else
+    vty_out (vty, "%*s ", len, " ");
+    
+  vty_out (vty, "%s ", peer_uptime (bdi->start_time,
+	   timebuf, BGP_UPTIME_LEN));
+
+  if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)
+      && ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
+    vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo));
+  else
+    vty_out (vty, "%*s ", 8, " ");
+
+  /* Print attribute */
+  attr = binfo->attr;
+  if (attr)
+    {
+      /* Print aspath */
+      if (attr->aspath)
+	aspath_print_vty (vty, attr->aspath);
+
+      /* Print origin */
+      if (strlen (attr->aspath->str) == 0)
+	vty_out (vty, "%s", bgp_origin_str[attr->origin]);
+      else
+	vty_out (vty, " %s", bgp_origin_str[attr->origin]);
+    }
+  vty_out (vty, "%s", VTY_NEWLINE);
+
+  return vty_calc_line (vty, length);
+}
+
+void
+route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, 
+		      struct bgp_info *binfo, afi_t afi, safi_t safi)
+{
+  char buf[INET6_ADDRSTRLEN];
+  char buf1[BUFSIZ];
+  struct attr *attr;
+  int sockunion_vty_out (struct vty *, union sockunion *);
+	
+  attr = binfo->attr;
+
+  if (attr)
+    {
+      /* Line1 display AS-path, Aggregator */
+      if (attr->aspath)
+	{
+	  vty_out (vty, "  ");
+	  if (attr->aspath->length == 0)
+	    vty_out (vty, "Local");
+	  else
+	    aspath_print_vty (vty, attr->aspath);
+	}
+
+      if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)
+	  || CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)
+	  || CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
+	  || CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)
+	  || CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
+	{
+	  vty_out (vty, ",");
+
+	  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))
+	    vty_out (vty, " (aggregated by %d %s)", attr->aggregator_as,
+		     inet_ntoa (attr->aggregator_addr));
+	  if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
+	    vty_out (vty, " (Received from a RR-client)");
+	  if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
+	    vty_out (vty, " (Received from a RS-client)");
+	  if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
+	    vty_out (vty, " (history entry)");
+	  else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
+	    vty_out (vty, " (suppressed due to dampening)");
+	}
+      vty_out (vty, "%s", VTY_NEWLINE);
+	  
+      /* Line2 display Next-hop, Neighbor, Router-id */
+      if (p->family == AF_INET)
+	{
+	  vty_out (vty, "    %s", safi == SAFI_MPLS_VPN ?
+		   inet_ntoa (attr->mp_nexthop_global_in) :
+		   inet_ntoa (attr->nexthop));
+	}
+#ifdef HAVE_IPV6
+      else
+	{
+	  vty_out (vty, "    %s",
+		   inet_ntop (AF_INET6, &attr->mp_nexthop_global,
+			      buf, INET6_ADDRSTRLEN));
+	}
+#endif /* HAVE_IPV6 */
+
+      if (binfo->peer == bgp->peer_self)
+	{
+	  vty_out (vty, " from %s ", 
+		   p->family == AF_INET ? "0.0.0.0" : "::");
+	  vty_out (vty, "(%s)", inet_ntoa(bgp->router_id));
+	}
+      else
+	{
+	  if (! CHECK_FLAG (binfo->flags, BGP_INFO_VALID))
+	    vty_out (vty, " (inaccessible)"); 
+	  else if (binfo->igpmetric)
+	    vty_out (vty, " (metric %d)", binfo->igpmetric);
+	  vty_out (vty, " from %s", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN));
+	  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
+	    vty_out (vty, " (%s)", inet_ntoa (attr->originator_id));
+	  else
+	    vty_out (vty, " (%s)", inet_ntop (AF_INET, &binfo->peer->remote_id, buf1, BUFSIZ));
+	}
+      vty_out (vty, "%s", VTY_NEWLINE);
+
+#ifdef HAVE_IPV6
+      /* display nexthop local */
+      if (attr->mp_nexthop_len == 32)
+	{
+	  vty_out (vty, "    (%s)%s",
+		   inet_ntop (AF_INET6, &attr->mp_nexthop_local,
+			      buf, INET6_ADDRSTRLEN),
+		   VTY_NEWLINE);
+	}
+#endif /* HAVE_IPV6 */
+
+      /* Line 3 display Origin, Med, Locpref, Weight, valid, Int/Ext/Local, Atomic, best */
+      vty_out (vty, "      Origin %s", bgp_origin_long_str[attr->origin]);
+	  
+      if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
+	vty_out (vty, ", metric %d", attr->med);
+	  
+      if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
+	vty_out (vty, ", localpref %d", attr->local_pref);
+      else
+	vty_out (vty, ", localpref %d", bgp->default_local_pref);
+
+      if (attr->weight != 0)
+	vty_out (vty, ", weight %d", attr->weight);
+	
+      if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
+	vty_out (vty, ", valid");
+
+      if (binfo->peer != bgp->peer_self)
+	{
+	  if (binfo->peer->as == binfo->peer->local_as)
+	    vty_out (vty, ", internal");
+	  else 
+	    vty_out (vty, ", %s", 
+		     (bgp_confederation_peers_check(bgp, binfo->peer->as) ? "confed-external" : "external"));
+	}
+      else if (binfo->sub_type == BGP_ROUTE_AGGREGATE)
+	vty_out (vty, ", aggregated, local");
+      else if (binfo->type != ZEBRA_ROUTE_BGP)
+	vty_out (vty, ", sourced");
+      else
+	vty_out (vty, ", sourced, local");
+
+      if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
+	vty_out (vty, ", atomic-aggregate");
+	  
+      if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))
+	vty_out (vty, ", best");
+
+      vty_out (vty, "%s", VTY_NEWLINE);
+	  
+      /* Line 4 display Community */
+      if (attr->community)
+	vty_out (vty, "      Community: %s%s", attr->community->str,
+		 VTY_NEWLINE);
+	  
+      /* Line 5 display Extended-community */
+      if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
+	vty_out (vty, "      Extended Community: %s%s", attr->ecommunity->str,
+		 VTY_NEWLINE);
+	  
+      /* Line 6 display Originator, Cluster-id */
+      if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) ||
+	  (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)))
+	{
+	  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
+	    vty_out (vty, "      Originator: %s", inet_ntoa (attr->originator_id));
+
+	  if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))
+	    {
+	      int i;
+	      vty_out (vty, ", Cluster list: ");
+	      for (i = 0; i < attr->cluster->length / 4; i++)
+		vty_out (vty, "%s ", inet_ntoa (attr->cluster->list[i]));
+	    }
+	  vty_out (vty, "%s", VTY_NEWLINE);
+	}
+
+      if (binfo->damp_info)
+	bgp_damp_info_vty (vty, binfo);
+
+      /* Line 7 display Uptime */
+      vty_out (vty, "      Last update: %s", ctime (&binfo->uptime));
+    }
+  vty_out (vty, "%s", VTY_NEWLINE);
+}  
+
+#define BGP_SHOW_HEADER "   Network          Next Hop            Metric LocPrf Weight Path%s"
+#define BGP_SHOW_DAMP_HEADER "   Network          From             Reuse    Path%s"
+#define BGP_SHOW_FLAP_HEADER "   Network          From            Flaps Duration Reuse    Path%s"
+
+enum bgp_show_type
+{
+  bgp_show_type_normal,
+  bgp_show_type_regexp,
+  bgp_show_type_prefix_list,
+  bgp_show_type_filter_list,
+  bgp_show_type_route_map,
+  bgp_show_type_neighbor,
+  bgp_show_type_cidr_only,
+  bgp_show_type_prefix_longer,
+  bgp_show_type_community_all,
+  bgp_show_type_community,
+  bgp_show_type_community_exact,
+  bgp_show_type_community_list,
+  bgp_show_type_community_list_exact,
+  bgp_show_type_flap_statistics,
+  bgp_show_type_flap_address,
+  bgp_show_type_flap_prefix,
+  bgp_show_type_flap_cidr_only,
+  bgp_show_type_flap_regexp,
+  bgp_show_type_flap_filter_list,
+  bgp_show_type_flap_prefix_list,
+  bgp_show_type_flap_prefix_longer,
+  bgp_show_type_flap_route_map,
+  bgp_show_type_flap_neighbor,
+  bgp_show_type_dampend_paths,
+  bgp_show_type_damp_neighbor
+};
+
+int
+bgp_show_callback (struct vty *vty, int unlock)
+{
+  struct bgp_node *rn;
+  struct bgp_info *ri;
+  int count;
+  int limit;
+  int display;
+
+  rn = vty->output_rn;
+  count = 0;
+  limit = ((vty->lines == 0) 
+	   ? 10 : (vty->lines > 0 
+		   ? vty->lines : vty->height - 2));
+  limit = limit > 0 ? limit : 2;
+
+  /* Quit of display. */
+  if (unlock && rn)
+    {
+      bgp_unlock_node (rn);
+      if (vty->output_clean)
+	(*vty->output_clean) (vty);
+      vty->output_rn = NULL;
+      vty->output_func = NULL;
+      vty->output_clean = NULL;
+      vty->output_arg = NULL;
+      return 0;
+    }
+
+  for (; rn; rn = bgp_route_next (rn)) 
+    if (rn->info != NULL)
+      {
+	display = 0;
+
+	for (ri = rn->info; ri; ri = ri->next)
+	  {
+	    if (vty->output_type == bgp_show_type_flap_statistics
+		|| vty->output_type == bgp_show_type_flap_address
+		|| vty->output_type == bgp_show_type_flap_prefix
+		|| vty->output_type == bgp_show_type_flap_cidr_only
+		|| vty->output_type == bgp_show_type_flap_regexp
+		|| vty->output_type == bgp_show_type_flap_filter_list
+		|| vty->output_type == bgp_show_type_flap_prefix_list
+		|| vty->output_type == bgp_show_type_flap_prefix_longer
+		|| vty->output_type == bgp_show_type_flap_route_map
+		|| vty->output_type == bgp_show_type_flap_neighbor
+		|| vty->output_type == bgp_show_type_dampend_paths
+		|| vty->output_type == bgp_show_type_damp_neighbor)
+	      {
+		if (! ri->damp_info)
+		  continue;
+	      }
+	    if (vty->output_type == bgp_show_type_regexp
+		|| vty->output_type == bgp_show_type_flap_regexp)
+	      {
+		regex_t *regex = vty->output_arg;
+
+		if (bgp_regexec (regex, ri->attr->aspath) == REG_NOMATCH)
+		  continue;
+	      }
+	    if (vty->output_type == bgp_show_type_prefix_list
+		|| vty->output_type == bgp_show_type_flap_prefix_list)
+	      {
+		struct prefix_list *plist = vty->output_arg;
+
+		if (prefix_list_apply (plist, &rn->p) != PREFIX_PERMIT)
+		  continue;
+	      }
+	    if (vty->output_type == bgp_show_type_filter_list
+		|| vty->output_type == bgp_show_type_flap_filter_list)
+	      {
+		struct as_list *as_list = vty->output_arg;
+
+		if (as_list_apply (as_list, ri->attr->aspath) != AS_FILTER_PERMIT)
+		  continue;
+	      }
+	    if (vty->output_type == bgp_show_type_route_map
+		|| vty->output_type == bgp_show_type_flap_route_map)
+	      {
+		struct route_map *rmap = vty->output_arg;
+		struct bgp_info binfo;
+		struct attr dummy_attr; 
+		int ret;
+
+		dummy_attr = *ri->attr;
+		binfo.peer = ri->peer;
+		binfo.attr = &dummy_attr;
+
+		ret = route_map_apply (rmap, &rn->p, RMAP_BGP, &binfo);
+
+		if (ret == RMAP_DENYMATCH)
+		  continue;
+	      }
+	    if (vty->output_type == bgp_show_type_neighbor
+		|| vty->output_type == bgp_show_type_flap_neighbor
+		|| vty->output_type == bgp_show_type_damp_neighbor)
+	      {
+		union sockunion *su = vty->output_arg;
+
+		if (ri->peer->su_remote == NULL || ! sockunion_same(ri->peer->su_remote, su))
+		  continue;
+	      }
+	    if (vty->output_type == bgp_show_type_cidr_only
+		|| vty->output_type == bgp_show_type_flap_cidr_only)
+	      {
+		u_int32_t destination;
+
+		destination = ntohl (rn->p.u.prefix4.s_addr);
+		if (IN_CLASSC (destination) && rn->p.prefixlen == 24)
+		  continue;
+		if (IN_CLASSB (destination) && rn->p.prefixlen == 16)
+		  continue;
+		if (IN_CLASSA (destination) && rn->p.prefixlen == 8)
+		  continue;
+	      }
+	    if (vty->output_type == bgp_show_type_prefix_longer
+		|| vty->output_type == bgp_show_type_flap_prefix_longer)
+	      {
+		struct prefix *p = vty->output_arg;
+
+		if (! prefix_match (p, &rn->p))
+		  continue;
+	      }
+	    if (vty->output_type == bgp_show_type_community_all)
+	      {
+		if (! ri->attr->community)
+		  continue;
+	      }
+	    if (vty->output_type == bgp_show_type_community)
+	      {
+		struct community *com = vty->output_arg;
+
+		if (! ri->attr->community ||
+		    ! community_match (ri->attr->community, com))
+		  continue;
+	      }
+	    if (vty->output_type == bgp_show_type_community_exact)
+	      {
+		struct community *com = vty->output_arg;
+
+		if (! ri->attr->community ||
+		    ! community_cmp (ri->attr->community, com))
+		  continue;
+	      }
+	    if (vty->output_type == bgp_show_type_community_list)
+	      {
+		struct community_list *list = vty->output_arg;
+
+		if (! community_list_match (ri->attr->community, list))
+		  continue;
+	      }
+	    if (vty->output_type == bgp_show_type_community_list_exact)
+	      {
+		struct community_list *list = vty->output_arg;
+
+		if (! community_list_exact_match (ri->attr->community, list))
+		  continue;
+	      }
+	    if (vty->output_type == bgp_show_type_flap_address
+		|| vty->output_type == bgp_show_type_flap_prefix)
+	      {
+		struct prefix *p = vty->output_arg;
+
+		if (! prefix_match (&rn->p, p))
+		  continue;
+
+		if (vty->output_type == bgp_show_type_flap_prefix)
+		  if (p->prefixlen != rn->p.prefixlen)
+		    continue;
+	      }
+	    if (vty->output_type == bgp_show_type_dampend_paths
+		|| vty->output_type == bgp_show_type_damp_neighbor)
+	      {
+		if (! CHECK_FLAG (ri->flags, BGP_INFO_DAMPED)
+		    || CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
+		  continue;
+	      }
+
+	    if (vty->output_type == bgp_show_type_dampend_paths
+		|| vty->output_type == bgp_show_type_damp_neighbor)
+	      count += damp_route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST);
+	    else if (vty->output_type == bgp_show_type_flap_statistics
+		     || vty->output_type == bgp_show_type_flap_address
+		     || vty->output_type == bgp_show_type_flap_prefix
+		     || vty->output_type == bgp_show_type_flap_cidr_only
+		     || vty->output_type == bgp_show_type_flap_regexp
+		     || vty->output_type == bgp_show_type_flap_filter_list
+		     || vty->output_type == bgp_show_type_flap_prefix_list
+		     || vty->output_type == bgp_show_type_flap_prefix_longer
+		     || vty->output_type == bgp_show_type_flap_route_map
+		     || vty->output_type == bgp_show_type_flap_neighbor)
+	      count += flap_route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST);
+	    else
+	      count += route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST);
+	    display++;
+	  }
+
+	if (display)
+	  vty->output_count++;
+
+	/* Remember current pointer then suspend output. */
+	if (count >= limit)
+	  {
+	    vty->status = VTY_CONTINUE;
+	    vty->output_rn = bgp_route_next (rn);;
+	    vty->output_func = bgp_show_callback;
+	    return 0;
+	  }
+      }
+
+  /* Total line display. */
+  if (vty->output_count)
+    vty_out (vty, "%sTotal number of prefixes %ld%s",
+	     VTY_NEWLINE, vty->output_count, VTY_NEWLINE);
+
+  if (vty->output_clean)
+    (*vty->output_clean) (vty);
+
+  vty->status = VTY_CONTINUE;
+  vty->output_rn = NULL;
+  vty->output_func = NULL;
+  vty->output_clean = NULL;
+  vty->output_arg = NULL;
+
+  return 0;
+}
+
+int
+bgp_show (struct vty *vty, char *view_name, afi_t afi, safi_t safi,
+	  enum bgp_show_type type)
+{
+  struct bgp *bgp;
+  struct bgp_info *ri;
+  struct bgp_node *rn;
+  struct bgp_table *table;
+  int header = 1;
+  int count;
+  int limit;
+  int display;
+
+  limit = ((vty->lines == 0) 
+	   ? 10 : (vty->lines > 0 
+		   ? vty->lines : vty->height - 2));
+  limit = limit > 0 ? limit : 2;
+
+  /* BGP structure lookup. */
+  if (view_name)
+    {
+      bgp = bgp_lookup_by_name (view_name);
+      if (bgp == NULL)
+	{
+	  vty_out (vty, "Can't find BGP view %s%s", view_name, VTY_NEWLINE);
+	  return CMD_WARNING;
+	}
+    }
+  else
+    {
+      bgp = bgp_get_default ();
+      if (bgp == NULL)
+	{
+	  vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	}
+    }
+
+  count = 0;
+
+  /* This is first entry point, so reset total line. */
+  vty->output_count = 0;
+  vty->output_type = type;
+
+  table = bgp->rib[afi][safi];
+
+  /* Start processing of routes. */
+  for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) 
+    if (rn->info != NULL)
+      {
+	display = 0;
+
+	for (ri = rn->info; ri; ri = ri->next)
+	  {
+	    if (vty->output_type == bgp_show_type_flap_statistics
+		|| type == bgp_show_type_flap_address
+		|| type == bgp_show_type_flap_prefix
+		|| type == bgp_show_type_flap_cidr_only
+		|| type == bgp_show_type_flap_regexp
+		|| type == bgp_show_type_flap_filter_list
+		|| type == bgp_show_type_flap_prefix_list
+		|| type == bgp_show_type_flap_prefix_longer
+		|| type == bgp_show_type_flap_route_map
+		|| type == bgp_show_type_flap_neighbor
+		|| type == bgp_show_type_dampend_paths
+		|| type == bgp_show_type_damp_neighbor)
+	      {
+		if (! ri->damp_info)
+		  continue;
+	      }
+	    if (type == bgp_show_type_regexp
+		|| type == bgp_show_type_flap_regexp)
+	      {
+		regex_t *regex = vty->output_arg;
+		    
+		if (bgp_regexec (regex, ri->attr->aspath) == REG_NOMATCH)
+		  continue;
+	      }
+	    if (type == bgp_show_type_prefix_list
+		|| type == bgp_show_type_flap_prefix_list)
+	      {
+		struct prefix_list *plist = vty->output_arg;
+		    
+		if (prefix_list_apply (plist, &rn->p) != PREFIX_PERMIT)
+		  continue;
+	      }
+	    if (type == bgp_show_type_filter_list
+		|| type == bgp_show_type_flap_filter_list)
+	      {
+		struct as_list *as_list = vty->output_arg;
+
+		if (as_list_apply (as_list, ri->attr->aspath) != AS_FILTER_PERMIT)
+		  continue;
+	      }
+	    if (type == bgp_show_type_route_map
+		|| type == bgp_show_type_flap_route_map)
+	      {
+		struct route_map *rmap = vty->output_arg;
+		struct bgp_info binfo;
+		struct attr dummy_attr; 
+		int ret;
+
+		dummy_attr = *ri->attr;
+		binfo.peer = ri->peer;
+		binfo.attr = &dummy_attr;
+
+		ret = route_map_apply (rmap, &rn->p, RMAP_BGP, &binfo);
+
+		if (ret == RMAP_DENYMATCH)
+		  continue;
+	      }
+	    if (type == bgp_show_type_neighbor
+		|| type == bgp_show_type_flap_neighbor
+		|| type == bgp_show_type_damp_neighbor)
+	      {
+		union sockunion *su = vty->output_arg;
+
+		if (ri->peer->su_remote == NULL || ! sockunion_same(ri->peer->su_remote, su))
+		  continue;
+	      }
+	    if (type == bgp_show_type_cidr_only
+		|| type == bgp_show_type_flap_cidr_only)
+	      {
+		u_int32_t destination;
+
+		destination = ntohl (rn->p.u.prefix4.s_addr);
+		if (IN_CLASSC (destination) && rn->p.prefixlen == 24)
+		  continue;
+		if (IN_CLASSB (destination) && rn->p.prefixlen == 16)
+		  continue;
+		if (IN_CLASSA (destination) && rn->p.prefixlen == 8)
+		  continue;
+	      }
+	    if (type == bgp_show_type_prefix_longer
+		|| type == bgp_show_type_flap_prefix_longer)
+	      {
+		struct prefix *p = vty->output_arg;
+
+		if (! prefix_match (p, &rn->p))
+		  continue;
+	      }
+	    if (type == bgp_show_type_community_all)
+	      {
+		if (! ri->attr->community)
+		  continue;
+	      }
+	    if (type == bgp_show_type_community)
+	      {
+		struct community *com = vty->output_arg;
+
+		if (! ri->attr->community ||
+		    ! community_match (ri->attr->community, com))
+		  continue;
+	      }
+	    if (type == bgp_show_type_community_exact)
+	      {
+		struct community *com = vty->output_arg;
+
+		if (! ri->attr->community ||
+		    ! community_cmp (ri->attr->community, com))
+		  continue;
+	      }
+	    if (type == bgp_show_type_community_list)
+	      {
+		struct community_list *list = vty->output_arg;
+
+		if (! community_list_match (ri->attr->community, list))
+		  continue;
+	      }
+	    if (type == bgp_show_type_community_list_exact)
+	      {
+		struct community_list *list = vty->output_arg;
+
+		if (! community_list_exact_match (ri->attr->community, list))
+		  continue;
+	      }
+	    if (type == bgp_show_type_flap_address
+		|| type == bgp_show_type_flap_prefix)
+	      {
+		struct prefix *p = vty->output_arg;
+
+		if (! prefix_match (&rn->p, p))
+		  continue;
+
+		if (type == bgp_show_type_flap_prefix)
+		  if (p->prefixlen != rn->p.prefixlen)
+		    continue;
+	      }
+	    if (type == bgp_show_type_dampend_paths
+		|| type == bgp_show_type_damp_neighbor)
+	      {
+		if (! CHECK_FLAG (ri->flags, BGP_INFO_DAMPED)
+		    || CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
+		  continue;
+	      }
+
+	    if (header)
+	      {
+		vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE);
+		vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s", VTY_NEWLINE);
+		vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s", VTY_NEWLINE, VTY_NEWLINE);
+		if (type == bgp_show_type_dampend_paths
+		    || type == bgp_show_type_damp_neighbor)
+		  vty_out (vty, BGP_SHOW_DAMP_HEADER, VTY_NEWLINE);
+		else if (type == bgp_show_type_flap_statistics
+			 || type == bgp_show_type_flap_address
+			 || type == bgp_show_type_flap_prefix
+			 || type == bgp_show_type_flap_cidr_only
+			 || type == bgp_show_type_flap_regexp
+			 || type == bgp_show_type_flap_filter_list
+			 || type == bgp_show_type_flap_prefix_list
+			 || type == bgp_show_type_flap_prefix_longer
+			 || type == bgp_show_type_flap_route_map
+			 || type == bgp_show_type_flap_neighbor)
+		  vty_out (vty, BGP_SHOW_FLAP_HEADER, VTY_NEWLINE);
+		else
+		  vty_out (vty, BGP_SHOW_HEADER, VTY_NEWLINE);
+		count += 5;
+		header = 0;
+	      }
+
+	    if (type == bgp_show_type_dampend_paths
+		|| type == bgp_show_type_damp_neighbor)
+	      count += damp_route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST);
+	    else if (type == bgp_show_type_flap_statistics
+		     || type == bgp_show_type_flap_address
+		     || type == bgp_show_type_flap_prefix
+		     || type == bgp_show_type_flap_cidr_only
+		     || type == bgp_show_type_flap_regexp
+		     || type == bgp_show_type_flap_filter_list
+		     || type == bgp_show_type_flap_prefix_list
+		     || type == bgp_show_type_flap_prefix_longer
+		     || type == bgp_show_type_flap_route_map
+		     || type == bgp_show_type_flap_neighbor)
+	      count += flap_route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST);
+	    else
+	      count += route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST);
+	    display++;
+	  }
+	if (display)
+	  vty->output_count++;
+
+	/* Remember current pointer then suspend output. */
+	if (count >= limit  && vty->type != VTY_SHELL_SERV)
+	  {
+	    vty->status = VTY_START;
+	    vty->output_rn = bgp_route_next (rn);
+	    vty->output_func = bgp_show_callback;
+	    vty->output_type = type;
+
+	    return CMD_SUCCESS;
+	  }
+      }
+
+  /* No route is displayed */
+  if (vty->output_count == 0)
+    {
+      if (type == bgp_show_type_normal)
+	vty_out (vty, "No BGP network exists%s", VTY_NEWLINE);
+    }
+  else
+    vty_out (vty, "%sTotal number of prefixes %ld%s",
+	     VTY_NEWLINE, vty->output_count, VTY_NEWLINE);
+
+  /* Clean up allocated resources. */
+  if (vty->output_clean)
+    (*vty->output_clean) (vty);
+
+  vty->status = VTY_START;
+  vty->output_rn = NULL;
+  vty->output_func = NULL;
+  vty->output_clean = NULL;
+  vty->output_arg = NULL;
+
+  return CMD_SUCCESS;
+}
+
+/* Header of detailed BGP route information */
+void
+route_vty_out_detail_header (struct vty *vty, struct bgp *bgp,
+			     struct bgp_node *rn,
+                             struct prefix_rd *prd, afi_t afi, safi_t safi)
+{
+  struct bgp_info *ri;
+  struct prefix *p;
+  struct peer *peer;
+  struct listnode *nn;
+  char buf1[INET6_ADDRSTRLEN];
+  char buf2[INET6_ADDRSTRLEN];
+  int count = 0;
+  int best = 0;
+  int suppress = 0;
+  int no_export = 0;
+  int no_advertise = 0;
+  int local_as = 0;
+  int first = 0;
+
+  p = &rn->p;
+  vty_out (vty, "BGP routing table entry for %s%s%s/%d%s",
+	   (safi == SAFI_MPLS_VPN ?
+	   prefix_rd2str (prd, buf1, RD_ADDRSTRLEN) : ""),
+	   safi == SAFI_MPLS_VPN ? ":" : "",
+	   inet_ntop (p->family, &p->u.prefix, buf2, INET6_ADDRSTRLEN),
+	   p->prefixlen, VTY_NEWLINE);
+
+  for (ri = rn->info; ri; ri = ri->next)
+    {
+      count++;
+      if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED))
+	{
+	  best = count;
+	  if (ri->suppress)
+	    suppress = 1;
+	  if (ri->attr->community != NULL)
+	    {
+	      if (community_include (ri->attr->community, COMMUNITY_NO_ADVERTISE))
+		no_advertise = 1;
+	      if (community_include (ri->attr->community, COMMUNITY_NO_EXPORT))
+		no_export = 1;
+	      if (community_include (ri->attr->community, COMMUNITY_LOCAL_AS))
+		local_as = 1;
+	    }
+	}
+    }
+
+  vty_out (vty, "Paths: (%d available", count);
+  if (best)
+    {
+      vty_out (vty, ", best #%d", best);
+      if (safi == SAFI_UNICAST)
+	vty_out (vty, ", table Default-IP-Routing-Table");
+    }
+  else
+    vty_out (vty, ", no best path");
+  if (no_advertise)
+    vty_out (vty, ", not advertised to any peer");
+  else if (no_export)
+    vty_out (vty, ", not advertised to EBGP peer");
+  else if (local_as)
+    vty_out (vty, ", not advertised outside local AS");
+  if (suppress)
+    vty_out (vty, ", Advertisements suppressed by an aggregate.");
+  vty_out (vty, ")%s", VTY_NEWLINE);
+
+  /* advertised peer */
+  LIST_LOOP (bgp->peer, peer, nn)
+    {
+      if (bgp_adj_out_lookup (peer, p, afi, safi, rn))
+	{
+	  if (! first)
+	    vty_out (vty, "  Advertised to non peer-group peers:%s ", VTY_NEWLINE);
+	  vty_out (vty, " %s", sockunion2str (&peer->su, buf1, SU_ADDRSTRLEN));
+	  first = 1;
+	}
+    }
+  if (! first)
+    vty_out (vty, "  Not advertised to any peer");
+  vty_out (vty, "%s", VTY_NEWLINE);
+}
+
+/* Display specified route of BGP table. */
+int
+bgp_show_route (struct vty *vty, char *view_name, char *ip_str,
+		afi_t afi, safi_t safi, struct prefix_rd *prd,
+		int prefix_check)
+{
+  int ret;
+  int header;
+  int display = 0;
+  struct prefix match;
+  struct bgp_node *rn;
+  struct bgp_node *rm;
+  struct bgp_info *ri;
+  struct bgp *bgp;
+  struct bgp_table *table;
+
+  /* BGP structure lookup. */
+  if (view_name)
+    {
+      bgp = bgp_lookup_by_name (view_name);
+      if (bgp == NULL)
+	{
+	  vty_out (vty, "Can't find BGP view %s%s", view_name, VTY_NEWLINE);
+	  return CMD_WARNING;
+	}
+    }
+  else
+    {
+      bgp = bgp_get_default ();
+      if (bgp == NULL)
+	{
+	  vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	}
+    }
+
+  /* Check IP address argument. */
+  ret = str2prefix (ip_str, &match);
+  if (! ret)
+    {
+      vty_out (vty, "address is malformed%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  match.family = afi2family (afi);
+
+  if (safi == SAFI_MPLS_VPN)
+    {
+      for (rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_MPLS_VPN]); rn; rn = bgp_route_next (rn))
+        {
+          if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
+            continue;
+
+          if ((table = rn->info) != NULL)
+            {
+              header = 1;
+
+              if ((rm = bgp_node_match (table, &match)) != NULL)
+                {
+                  if (prefix_check && rm->p.prefixlen != match.prefixlen)
+                    continue;
+
+                  for (ri = rm->info; ri; ri = ri->next)
+                    {
+                      if (header)
+                        {
+                          route_vty_out_detail_header (vty, bgp, rm, (struct prefix_rd *)&rn->p,
+                                                       AFI_IP, SAFI_MPLS_VPN);
+
+                          header = 0;
+                        }
+                      display++;
+                      route_vty_out_detail (vty, bgp, &rm->p, ri, AFI_IP, SAFI_MPLS_VPN);
+                    }
+                }
+            }
+        }
+    }
+  else
+    {
+      header = 1;
+
+      if ((rn = bgp_node_match (bgp->rib[afi][safi], &match)) != NULL)
+        {
+          if (! prefix_check || rn->p.prefixlen == match.prefixlen)
+            {
+              for (ri = rn->info; ri; ri = ri->next)
+                {
+                  if (header)
+                    {
+                      route_vty_out_detail_header (vty, bgp, rn, NULL, afi, safi);
+                      header = 0;
+                    }
+                  display++;
+                  route_vty_out_detail (vty, bgp, &rn->p, ri, afi, safi);
+                }
+            }
+        }
+    }
+
+  if (! display)
+    {
+      vty_out (vty, "%% Network not in table%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return CMD_SUCCESS;
+}
+
+/* BGP route print out function. */
+DEFUN (show_ip_bgp,
+       show_ip_bgp_cmd,
+       "show ip bgp",
+       SHOW_STR
+       IP_STR
+       BGP_STR)
+{
+  return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, bgp_show_type_normal);
+}
+
+DEFUN (show_ip_bgp_ipv4,
+       show_ip_bgp_ipv4_cmd,
+       "show ip bgp ipv4 (unicast|multicast)",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_show (vty, NULL, AFI_IP, SAFI_MULTICAST, bgp_show_type_normal);
+ 
+  return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, bgp_show_type_normal);
+}
+
+DEFUN (show_ip_bgp_route,
+       show_ip_bgp_route_cmd,
+       "show ip bgp A.B.C.D",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Network in the BGP routing table to display\n")
+{
+  return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 0);
+}
+
+DEFUN (show_ip_bgp_ipv4_route,
+       show_ip_bgp_ipv4_route_cmd,
+       "show ip bgp ipv4 (unicast|multicast) A.B.C.D",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Network in the BGP routing table to display\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 0);
+
+  return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 0);
+}
+
+DEFUN (show_ip_bgp_vpnv4_all_route,
+       show_ip_bgp_vpnv4_all_route_cmd,
+       "show ip bgp vpnv4 all A.B.C.D",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display VPNv4 NLRI specific information\n"
+       "Display information about all VPNv4 NLRIs\n"
+       "Network in the BGP routing table to display\n")
+{
+  return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_MPLS_VPN, NULL, 0);
+}
+
+DEFUN (show_ip_bgp_vpnv4_rd_route,
+       show_ip_bgp_vpnv4_rd_route_cmd,
+       "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn A.B.C.D",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display VPNv4 NLRI specific information\n"
+       "Display information for a route distinguisher\n"
+       "VPN Route Distinguisher\n"
+       "Network in the BGP routing table to display\n")
+{
+  int ret;
+  struct prefix_rd prd;
+
+  ret = str2prefix_rd (argv[0], &prd);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MPLS_VPN, &prd, 0);
+}
+
+DEFUN (show_ip_bgp_prefix,
+       show_ip_bgp_prefix_cmd,
+       "show ip bgp A.B.C.D/M",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
+{
+  return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 1);
+}
+
+DEFUN (show_ip_bgp_ipv4_prefix,
+       show_ip_bgp_ipv4_prefix_cmd,
+       "show ip bgp ipv4 (unicast|multicast) A.B.C.D/M",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 1);
+
+  return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 1);
+}
+
+DEFUN (show_ip_bgp_vpnv4_all_prefix,
+       show_ip_bgp_vpnv4_all_prefix_cmd,
+       "show ip bgp vpnv4 all A.B.C.D/M",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display VPNv4 NLRI specific information\n"
+       "Display information about all VPNv4 NLRIs\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
+{
+  return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_MPLS_VPN, NULL, 1);
+}
+
+DEFUN (show_ip_bgp_vpnv4_rd_prefix,
+       show_ip_bgp_vpnv4_rd_prefix_cmd,
+       "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn A.B.C.D/M",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display VPNv4 NLRI specific information\n"
+       "Display information for a route distinguisher\n"
+       "VPN Route Distinguisher\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
+{
+  int ret;
+  struct prefix_rd prd;
+
+  ret = str2prefix_rd (argv[0], &prd);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MPLS_VPN, &prd, 1);
+}
+
+DEFUN (show_ip_bgp_view,
+       show_ip_bgp_view_cmd,
+       "show ip bgp view WORD",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "BGP view\n"
+       "BGP view name\n")
+{
+  return bgp_show (vty, argv[0], AFI_IP, SAFI_UNICAST, bgp_show_type_normal);
+}
+
+DEFUN (show_ip_bgp_view_route,
+       show_ip_bgp_view_route_cmd,
+       "show ip bgp view WORD A.B.C.D",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "Network in the BGP routing table to display\n")
+{
+  return bgp_show_route (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, NULL, 0);
+}
+
+DEFUN (show_ip_bgp_view_prefix,
+       show_ip_bgp_view_prefix_cmd,
+       "show ip bgp view WORD A.B.C.D/M",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "BGP view\n"
+       "BGP view name\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
+{
+  return bgp_show_route (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, NULL, 1);
+}
+
+#ifdef HAVE_IPV6
+DEFUN (show_bgp,
+       show_bgp_cmd,
+       "show bgp",
+       SHOW_STR
+       BGP_STR)
+{
+  return bgp_show (vty, NULL, AFI_IP6, SAFI_UNICAST, bgp_show_type_normal);
+}
+
+ALIAS (show_bgp,
+       show_bgp_ipv6_cmd,
+       "show bgp ipv6",
+       SHOW_STR
+       BGP_STR
+       "Address family\n")
+
+/* old command */
+DEFUN (show_ipv6_bgp,
+       show_ipv6_bgp_cmd,
+       "show ipv6 bgp",
+       SHOW_STR
+       IP_STR
+       BGP_STR)
+{
+  return bgp_show (vty, NULL, AFI_IP6, SAFI_UNICAST, bgp_show_type_normal);
+}
+
+DEFUN (show_bgp_route,
+       show_bgp_route_cmd,
+       "show bgp X:X::X:X",
+       SHOW_STR
+       BGP_STR
+       "Network in the BGP routing table to display\n")
+{
+  return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0);
+}
+
+ALIAS (show_bgp_route,
+       show_bgp_ipv6_route_cmd,
+       "show bgp ipv6 X:X::X:X",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Network in the BGP routing table to display\n")
+
+/* old command */
+DEFUN (show_ipv6_bgp_route,
+       show_ipv6_bgp_route_cmd,
+       "show ipv6 bgp X:X::X:X",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Network in the BGP routing table to display\n")
+{
+  return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0);
+}
+
+DEFUN (show_bgp_prefix,
+       show_bgp_prefix_cmd,
+       "show bgp X:X::X:X/M",
+       SHOW_STR
+       BGP_STR
+       "IPv6 prefix <network>/<length>\n")
+{
+  return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 1);
+}
+
+ALIAS (show_bgp_prefix,
+       show_bgp_ipv6_prefix_cmd,
+       "show bgp ipv6 X:X::X:X/M",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "IPv6 prefix <network>/<length>\n")
+
+/* old command */
+DEFUN (show_ipv6_bgp_prefix,
+       show_ipv6_bgp_prefix_cmd,
+       "show ipv6 bgp X:X::X:X/M",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
+{
+  return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 1);
+}
+
+/* old command */
+DEFUN (show_ipv6_mbgp,
+       show_ipv6_mbgp_cmd,
+       "show ipv6 mbgp",
+       SHOW_STR
+       IP_STR
+       MBGP_STR)
+{
+  return bgp_show (vty, NULL, AFI_IP6, SAFI_MULTICAST, bgp_show_type_normal);
+}
+
+/* old command */
+DEFUN (show_ipv6_mbgp_route,
+       show_ipv6_mbgp_route_cmd,
+       "show ipv6 mbgp X:X::X:X",
+       SHOW_STR
+       IP_STR
+       MBGP_STR
+       "Network in the MBGP routing table to display\n")
+{
+  return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_MULTICAST, NULL, 0);
+}
+
+/* old command */
+DEFUN (show_ipv6_mbgp_prefix,
+       show_ipv6_mbgp_prefix_cmd,
+       "show ipv6 mbgp X:X::X:X/M",
+       SHOW_STR
+       IP_STR
+       MBGP_STR
+       "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
+{
+  return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_MULTICAST, NULL, 1);
+}
+#endif
+
+void
+bgp_show_regexp_clean (struct vty *vty)
+{
+  bgp_regex_free (vty->output_arg);
+}
+
+int
+bgp_show_regexp (struct vty *vty, int argc, char **argv, afi_t afi,
+		 safi_t safi, enum bgp_show_type type)
+{
+  int i;
+  struct buffer *b;
+  char *regstr;
+  int first;
+  regex_t *regex;
+  
+  first = 0;
+  b = buffer_new (1024);
+  for (i = 0; i < argc; i++)
+    {
+      if (first)
+	buffer_putc (b, ' ');
+      else
+	{
+	  if ((strcmp (argv[i], "unicast") == 0) || (strcmp (argv[i], "multicast") == 0))
+	    continue;
+	  first = 1;
+	}
+
+      buffer_putstr (b, argv[i]);
+    }
+  buffer_putc (b, '\0');
+
+  regstr = buffer_getstr (b);
+  buffer_free (b);
+
+  regex = bgp_regcomp (regstr);
+  if (! regex)
+    {
+      vty_out (vty, "Can't compile regexp %s%s", argv[0],
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  vty->output_arg = regex;
+  vty->output_clean = bgp_show_regexp_clean;
+
+  return bgp_show (vty, NULL, afi, safi, type);
+}
+
+DEFUN (show_ip_bgp_regexp, 
+       show_ip_bgp_regexp_cmd,
+       "show ip bgp regexp .LINE",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display routes matching the AS path regular expression\n"
+       "A regular-expression to match the BGP AS paths\n")
+{
+  return bgp_show_regexp (vty, argc, argv, AFI_IP, SAFI_UNICAST,
+			  bgp_show_type_regexp);
+}
+
+DEFUN (show_ip_bgp_flap_regexp, 
+       show_ip_bgp_flap_regexp_cmd,
+       "show ip bgp flap-statistics regexp .LINE",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display flap statistics of routes\n"
+       "Display routes matching the AS path regular expression\n"
+       "A regular-expression to match the BGP AS paths\n")
+{
+  return bgp_show_regexp (vty, argc, argv, AFI_IP, SAFI_UNICAST,
+			  bgp_show_type_flap_regexp);
+}
+
+DEFUN (show_ip_bgp_ipv4_regexp, 
+       show_ip_bgp_ipv4_regexp_cmd,
+       "show ip bgp ipv4 (unicast|multicast) regexp .LINE",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Display routes matching the AS path regular expression\n"
+       "A regular-expression to match the BGP AS paths\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_show_regexp (vty, argc, argv, AFI_IP, SAFI_MULTICAST,
+			    bgp_show_type_regexp);
+
+  return bgp_show_regexp (vty, argc, argv, AFI_IP, SAFI_UNICAST,
+			  bgp_show_type_regexp);
+}
+
+#ifdef HAVE_IPV6
+DEFUN (show_bgp_regexp, 
+       show_bgp_regexp_cmd,
+       "show bgp regexp .LINE",
+       SHOW_STR
+       BGP_STR
+       "Display routes matching the AS path regular expression\n"
+       "A regular-expression to match the BGP AS paths\n")
+{
+  return bgp_show_regexp (vty, argc, argv, AFI_IP6, SAFI_UNICAST,
+			  bgp_show_type_regexp);
+}
+
+ALIAS (show_bgp_regexp, 
+       show_bgp_ipv6_regexp_cmd,
+       "show bgp ipv6 regexp .LINE",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Display routes matching the AS path regular expression\n"
+       "A regular-expression to match the BGP AS paths\n")
+
+/* old command */
+DEFUN (show_ipv6_bgp_regexp, 
+       show_ipv6_bgp_regexp_cmd,
+       "show ipv6 bgp regexp .LINE",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display routes matching the AS path regular expression\n"
+       "A regular-expression to match the BGP AS paths\n")
+{
+  return bgp_show_regexp (vty, argc, argv, AFI_IP6, SAFI_UNICAST,
+			  bgp_show_type_regexp);
+}
+
+/* old command */
+DEFUN (show_ipv6_mbgp_regexp, 
+       show_ipv6_mbgp_regexp_cmd,
+       "show ipv6 mbgp regexp .LINE",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display routes matching the AS path regular expression\n"
+       "A regular-expression to match the MBGP AS paths\n")
+{
+  return bgp_show_regexp (vty, argc, argv, AFI_IP6, SAFI_MULTICAST,
+			  bgp_show_type_regexp);
+}
+#endif /* HAVE_IPV6 */
+
+int
+bgp_show_prefix_list (struct vty *vty, char *prefix_list_str, afi_t afi,
+		      safi_t safi, enum bgp_show_type type)
+{
+  struct prefix_list *plist;
+
+  plist = prefix_list_lookup (afi, prefix_list_str);
+  if (plist == NULL)
+    {
+      vty_out (vty, "%% %s is not a valid prefix-list name%s",
+               prefix_list_str, VTY_NEWLINE);	    
+      return CMD_WARNING;
+    }
+
+  vty->output_arg = plist;
+
+  return bgp_show (vty, NULL, afi, safi, type);
+}
+
+DEFUN (show_ip_bgp_prefix_list, 
+       show_ip_bgp_prefix_list_cmd,
+       "show ip bgp prefix-list WORD",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display routes conforming to the prefix-list\n"
+       "IP prefix-list name\n")
+{
+  return bgp_show_prefix_list (vty, argv[0], AFI_IP, SAFI_UNICAST,
+			       bgp_show_type_prefix_list);
+}
+
+DEFUN (show_ip_bgp_flap_prefix_list, 
+       show_ip_bgp_flap_prefix_list_cmd,
+       "show ip bgp flap-statistics prefix-list WORD",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display flap statistics of routes\n"
+       "Display routes conforming to the prefix-list\n"
+       "IP prefix-list name\n")
+{
+  return bgp_show_prefix_list (vty, argv[0], AFI_IP, SAFI_UNICAST,
+			       bgp_show_type_flap_prefix_list);
+}
+
+DEFUN (show_ip_bgp_ipv4_prefix_list, 
+       show_ip_bgp_ipv4_prefix_list_cmd,
+       "show ip bgp ipv4 (unicast|multicast) prefix-list WORD",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Display routes conforming to the prefix-list\n"
+       "IP prefix-list name\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_show_prefix_list (vty, argv[1], AFI_IP, SAFI_MULTICAST,
+			         bgp_show_type_prefix_list);
+
+  return bgp_show_prefix_list (vty, argv[1], AFI_IP, SAFI_UNICAST,
+			       bgp_show_type_prefix_list);
+}
+
+#ifdef HAVE_IPV6
+DEFUN (show_bgp_prefix_list, 
+       show_bgp_prefix_list_cmd,
+       "show bgp prefix-list WORD",
+       SHOW_STR
+       BGP_STR
+       "Display routes conforming to the prefix-list\n"
+       "IPv6 prefix-list name\n")
+{
+  return bgp_show_prefix_list (vty, argv[0], AFI_IP6, SAFI_UNICAST,
+			       bgp_show_type_prefix_list);
+}
+
+ALIAS (show_bgp_prefix_list, 
+       show_bgp_ipv6_prefix_list_cmd,
+       "show bgp ipv6 prefix-list WORD",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Display routes conforming to the prefix-list\n"
+       "IPv6 prefix-list name\n")
+
+/* old command */
+DEFUN (show_ipv6_bgp_prefix_list, 
+       show_ipv6_bgp_prefix_list_cmd,
+       "show ipv6 bgp prefix-list WORD",
+       SHOW_STR
+       IPV6_STR
+       BGP_STR
+       "Display routes matching the prefix-list\n"
+       "IPv6 prefix-list name\n")
+{
+  return bgp_show_prefix_list (vty, argv[0], AFI_IP6, SAFI_UNICAST,
+			       bgp_show_type_prefix_list);
+}
+
+/* old command */
+DEFUN (show_ipv6_mbgp_prefix_list, 
+       show_ipv6_mbgp_prefix_list_cmd,
+       "show ipv6 mbgp prefix-list WORD",
+       SHOW_STR
+       IPV6_STR
+       MBGP_STR
+       "Display routes matching the prefix-list\n"
+       "IPv6 prefix-list name\n")
+{
+  return bgp_show_prefix_list (vty, argv[0], AFI_IP6, SAFI_MULTICAST,
+			       bgp_show_type_prefix_list);
+}
+#endif /* HAVE_IPV6 */
+
+int
+bgp_show_filter_list (struct vty *vty, char *filter, afi_t afi,
+		      safi_t safi, enum bgp_show_type type)
+{
+  struct as_list *as_list;
+
+  as_list = as_list_lookup (filter);
+  if (as_list == NULL)
+    {
+      vty_out (vty, "%% %s is not a valid AS-path access-list name%s", filter, VTY_NEWLINE);	    
+      return CMD_WARNING;
+    }
+
+  vty->output_arg = as_list;
+
+  return bgp_show (vty, NULL, afi, safi, type);
+}
+
+DEFUN (show_ip_bgp_filter_list, 
+       show_ip_bgp_filter_list_cmd,
+       "show ip bgp filter-list WORD",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display routes conforming to the filter-list\n"
+       "Regular expression access list name\n")
+{
+  return bgp_show_filter_list (vty, argv[0], AFI_IP, SAFI_UNICAST,
+			       bgp_show_type_filter_list);
+}
+
+DEFUN (show_ip_bgp_flap_filter_list, 
+       show_ip_bgp_flap_filter_list_cmd,
+       "show ip bgp flap-statistics filter-list WORD",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display flap statistics of routes\n"
+       "Display routes conforming to the filter-list\n"
+       "Regular expression access list name\n")
+{
+  return bgp_show_filter_list (vty, argv[0], AFI_IP, SAFI_UNICAST,
+			       bgp_show_type_flap_filter_list);
+}
+
+DEFUN (show_ip_bgp_ipv4_filter_list, 
+       show_ip_bgp_ipv4_filter_list_cmd,
+       "show ip bgp ipv4 (unicast|multicast) filter-list WORD",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Display routes conforming to the filter-list\n"
+       "Regular expression access list name\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_show_filter_list (vty, argv[1], AFI_IP, SAFI_MULTICAST,
+			         bgp_show_type_filter_list);
+  
+  return bgp_show_filter_list (vty, argv[1], AFI_IP, SAFI_UNICAST,
+			       bgp_show_type_filter_list);
+}
+
+#ifdef HAVE_IPV6
+DEFUN (show_bgp_filter_list, 
+       show_bgp_filter_list_cmd,
+       "show bgp filter-list WORD",
+       SHOW_STR
+       BGP_STR
+       "Display routes conforming to the filter-list\n"
+       "Regular expression access list name\n")
+{
+  return bgp_show_filter_list (vty, argv[0], AFI_IP6, SAFI_UNICAST,
+			       bgp_show_type_filter_list);
+}
+
+ALIAS (show_bgp_filter_list, 
+       show_bgp_ipv6_filter_list_cmd,
+       "show bgp ipv6 filter-list WORD",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Display routes conforming to the filter-list\n"
+       "Regular expression access list name\n")
+
+/* old command */
+DEFUN (show_ipv6_bgp_filter_list, 
+       show_ipv6_bgp_filter_list_cmd,
+       "show ipv6 bgp filter-list WORD",
+       SHOW_STR
+       IPV6_STR
+       BGP_STR
+       "Display routes conforming to the filter-list\n"
+       "Regular expression access list name\n")
+{
+  return bgp_show_filter_list (vty, argv[0], AFI_IP6, SAFI_UNICAST,
+			       bgp_show_type_filter_list);
+}
+
+/* old command */
+DEFUN (show_ipv6_mbgp_filter_list, 
+       show_ipv6_mbgp_filter_list_cmd,
+       "show ipv6 mbgp filter-list WORD",
+       SHOW_STR
+       IPV6_STR
+       MBGP_STR
+       "Display routes conforming to the filter-list\n"
+       "Regular expression access list name\n")
+{
+  return bgp_show_filter_list (vty, argv[0], AFI_IP6, SAFI_MULTICAST,
+			       bgp_show_type_filter_list);
+}
+#endif /* HAVE_IPV6 */
+
+int
+bgp_show_route_map (struct vty *vty, char *rmap_str, afi_t afi,
+		    safi_t safi, enum bgp_show_type type)
+{
+  struct route_map *rmap;
+
+  rmap = route_map_lookup_by_name (rmap_str);
+  if (! rmap)
+    {
+      vty_out (vty, "%% %s is not a valid route-map name%s",
+	       rmap_str, VTY_NEWLINE);	    
+      return CMD_WARNING;
+    }
+
+  vty->output_arg = rmap;
+
+  return bgp_show (vty, NULL, afi, safi, type);
+}
+
+DEFUN (show_ip_bgp_route_map, 
+       show_ip_bgp_route_map_cmd,
+       "show ip bgp route-map WORD",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display routes matching the route-map\n"
+       "A route-map to match on\n")
+{
+  return bgp_show_route_map (vty, argv[0], AFI_IP, SAFI_UNICAST,
+			     bgp_show_type_route_map);
+}
+
+DEFUN (show_ip_bgp_flap_route_map, 
+       show_ip_bgp_flap_route_map_cmd,
+       "show ip bgp flap-statistics route-map WORD",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display flap statistics of routes\n"
+       "Display routes matching the route-map\n"
+       "A route-map to match on\n")
+{
+  return bgp_show_route_map (vty, argv[0], AFI_IP, SAFI_UNICAST,
+			     bgp_show_type_flap_route_map);
+}
+
+DEFUN (show_ip_bgp_ipv4_route_map, 
+       show_ip_bgp_ipv4_route_map_cmd,
+       "show ip bgp ipv4 (unicast|multicast) route-map WORD",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Display routes matching the route-map\n"
+       "A route-map to match on\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_show_route_map (vty, argv[1], AFI_IP, SAFI_MULTICAST,
+			       bgp_show_type_route_map);
+
+  return bgp_show_route_map (vty, argv[1], AFI_IP, SAFI_UNICAST,
+			     bgp_show_type_route_map);
+}
+
+DEFUN (show_bgp_route_map, 
+       show_bgp_route_map_cmd,
+       "show bgp route-map WORD",
+       SHOW_STR
+       BGP_STR
+       "Display routes matching the route-map\n"
+       "A route-map to match on\n")
+{
+  return bgp_show_route_map (vty, argv[0], AFI_IP6, SAFI_UNICAST,
+			     bgp_show_type_route_map);
+}
+
+ALIAS (show_bgp_route_map, 
+       show_bgp_ipv6_route_map_cmd,
+       "show bgp ipv6 route-map WORD",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Display routes matching the route-map\n"
+       "A route-map to match on\n")
+
+DEFUN (show_ip_bgp_cidr_only,
+       show_ip_bgp_cidr_only_cmd,
+       "show ip bgp cidr-only",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display only routes with non-natural netmasks\n")
+{
+    return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST,
+		     bgp_show_type_cidr_only);
+}
+
+DEFUN (show_ip_bgp_flap_cidr_only,
+       show_ip_bgp_flap_cidr_only_cmd,
+       "show ip bgp flap-statistics cidr-only",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display flap statistics of routes\n"
+       "Display only routes with non-natural netmasks\n")
+{
+  return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST,
+		   bgp_show_type_flap_cidr_only);
+}
+
+DEFUN (show_ip_bgp_ipv4_cidr_only,
+       show_ip_bgp_ipv4_cidr_only_cmd,
+       "show ip bgp ipv4 (unicast|multicast) cidr-only",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Display only routes with non-natural netmasks\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_show (vty, NULL, AFI_IP, SAFI_MULTICAST,
+		     bgp_show_type_cidr_only);
+
+  return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST,
+		     bgp_show_type_cidr_only);
+}
+
+DEFUN (show_ip_bgp_community_all,
+       show_ip_bgp_community_all_cmd,
+       "show ip bgp community",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display routes matching the communities\n")
+{
+  return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST,
+		     bgp_show_type_community_all);
+}
+
+DEFUN (show_ip_bgp_ipv4_community_all,
+       show_ip_bgp_ipv4_community_all_cmd,
+       "show ip bgp ipv4 (unicast|multicast) community",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Display routes matching the communities\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_show (vty, NULL, AFI_IP, SAFI_MULTICAST,
+		     bgp_show_type_community_all);
+ 
+  return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST,
+		   bgp_show_type_community_all);
+}
+
+#ifdef HAVE_IPV6
+DEFUN (show_bgp_community_all,
+       show_bgp_community_all_cmd,
+       "show bgp community",
+       SHOW_STR
+       BGP_STR
+       "Display routes matching the communities\n")
+{
+  return bgp_show (vty, NULL, AFI_IP6, SAFI_UNICAST,
+		   bgp_show_type_community_all);
+}
+
+ALIAS (show_bgp_community_all,
+       show_bgp_ipv6_community_all_cmd,
+       "show bgp ipv6 community",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Display routes matching the communities\n")
+
+/* old command */
+DEFUN (show_ipv6_bgp_community_all,
+       show_ipv6_bgp_community_all_cmd,
+       "show ipv6 bgp community",
+       SHOW_STR
+       IPV6_STR
+       BGP_STR
+       "Display routes matching the communities\n")
+{
+  return bgp_show (vty, NULL, AFI_IP6, SAFI_UNICAST,
+		   bgp_show_type_community_all);
+}
+
+/* old command */
+DEFUN (show_ipv6_mbgp_community_all,
+       show_ipv6_mbgp_community_all_cmd,
+       "show ipv6 mbgp community",
+       SHOW_STR
+       IPV6_STR
+       MBGP_STR
+       "Display routes matching the communities\n")
+{
+  return bgp_show (vty, NULL, AFI_IP6, SAFI_MULTICAST,
+		   bgp_show_type_community_all);
+}
+#endif /* HAVE_IPV6 */
+
+int
+bgp_show_community (struct vty *vty, int argc, char **argv, int exact,
+		                          u_int16_t afi, u_char safi)
+{
+  struct community *com;
+  struct buffer *b;
+  int i;
+  char *str;
+  int first = 0;
+
+  b = buffer_new (1024);
+  for (i = 0; i < argc; i++)
+    {
+      if (first)
+        buffer_putc (b, ' ');
+      else
+	{
+	  if ((strcmp (argv[i], "unicast") == 0) || (strcmp (argv[i], "multicast") == 0))
+	    continue;
+	  first = 1;
+	}
+      
+      buffer_putstr (b, argv[i]);
+    }
+  buffer_putc (b, '\0');
+
+  str = buffer_getstr (b);
+  buffer_free (b);
+
+  com = community_str2com (str);
+  free (str);
+  if (! com)
+    {
+      vty_out (vty, "%% Community malformed: %s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  vty->output_arg = com;
+
+  if (exact)
+    return bgp_show (vty, NULL, afi, safi, bgp_show_type_community_exact);
+
+  return bgp_show (vty, NULL, afi, safi, bgp_show_type_community);
+}
+
+DEFUN (show_ip_bgp_community,
+       show_ip_bgp_community_cmd,
+       "show ip bgp community (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+{
+  return bgp_show_community (vty, argc, argv, 0, AFI_IP, SAFI_UNICAST);
+}
+
+ALIAS (show_ip_bgp_community,
+       show_ip_bgp_community2_cmd,
+       "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+	
+ALIAS (show_ip_bgp_community,
+       show_ip_bgp_community3_cmd,
+       "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+	
+ALIAS (show_ip_bgp_community,
+       show_ip_bgp_community4_cmd,
+       "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+
+DEFUN (show_ip_bgp_ipv4_community,
+       show_ip_bgp_ipv4_community_cmd,
+       "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_show_community (vty, argc, argv, 0, AFI_IP, SAFI_MULTICAST);
+ 
+  return bgp_show_community (vty, argc, argv, 0, AFI_IP, SAFI_UNICAST);
+}
+
+ALIAS (show_ip_bgp_ipv4_community,
+       show_ip_bgp_ipv4_community2_cmd,
+       "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+	
+ALIAS (show_ip_bgp_ipv4_community,
+       show_ip_bgp_ipv4_community3_cmd,
+       "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+	
+ALIAS (show_ip_bgp_ipv4_community,
+       show_ip_bgp_ipv4_community4_cmd,
+       "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+
+DEFUN (show_ip_bgp_community_exact,
+       show_ip_bgp_community_exact_cmd,
+       "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+{
+  return bgp_show_community (vty, argc, argv, 1, AFI_IP, SAFI_UNICAST);
+}
+
+ALIAS (show_ip_bgp_community_exact,
+       show_ip_bgp_community2_exact_cmd,
+       "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+
+ALIAS (show_ip_bgp_community_exact,
+       show_ip_bgp_community3_exact_cmd,
+       "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+
+ALIAS (show_ip_bgp_community_exact,
+       show_ip_bgp_community4_exact_cmd,
+       "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+
+DEFUN (show_ip_bgp_ipv4_community_exact,
+       show_ip_bgp_ipv4_community_exact_cmd,
+       "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_show_community (vty, argc, argv, 1, AFI_IP, SAFI_MULTICAST);
+ 
+  return bgp_show_community (vty, argc, argv, 1, AFI_IP, SAFI_UNICAST);
+}
+
+ALIAS (show_ip_bgp_ipv4_community_exact,
+       show_ip_bgp_ipv4_community2_exact_cmd,
+       "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+
+ALIAS (show_ip_bgp_ipv4_community_exact,
+       show_ip_bgp_ipv4_community3_exact_cmd,
+       "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+       
+ALIAS (show_ip_bgp_ipv4_community_exact,
+       show_ip_bgp_ipv4_community4_exact_cmd,
+       "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+
+#ifdef HAVE_IPV6
+DEFUN (show_bgp_community,
+       show_bgp_community_cmd,
+       "show bgp community (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+{
+  return bgp_show_community (vty, argc, argv, 0, AFI_IP6, SAFI_UNICAST);
+}
+
+ALIAS (show_bgp_community,
+       show_bgp_ipv6_community_cmd,
+       "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+
+ALIAS (show_bgp_community,
+       show_bgp_community2_cmd,
+       "show bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+
+ALIAS (show_bgp_community,
+       show_bgp_ipv6_community2_cmd,
+       "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+	
+ALIAS (show_bgp_community,
+       show_bgp_community3_cmd,
+       "show bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+
+ALIAS (show_bgp_community,
+       show_bgp_ipv6_community3_cmd,
+       "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+
+ALIAS (show_bgp_community,
+       show_bgp_community4_cmd,
+       "show bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+
+ALIAS (show_bgp_community,
+       show_bgp_ipv6_community4_cmd,
+       "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+
+/* old command */
+DEFUN (show_ipv6_bgp_community,
+       show_ipv6_bgp_community_cmd,
+       "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       IPV6_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+{
+  return bgp_show_community (vty, argc, argv, 0, AFI_IP6, SAFI_UNICAST);
+}
+
+/* old command */
+ALIAS (show_ipv6_bgp_community,
+       show_ipv6_bgp_community2_cmd,
+       "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       IPV6_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+
+/* old command */
+ALIAS (show_ipv6_bgp_community,
+       show_ipv6_bgp_community3_cmd,
+       "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       IPV6_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+
+/* old command */
+ALIAS (show_ipv6_bgp_community,
+       show_ipv6_bgp_community4_cmd,
+       "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       IPV6_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+
+DEFUN (show_bgp_community_exact,
+       show_bgp_community_exact_cmd,
+       "show bgp community (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+{
+  return bgp_show_community (vty, argc, argv, 1, AFI_IP6, SAFI_UNICAST);
+}
+
+ALIAS (show_bgp_community_exact,
+       show_bgp_ipv6_community_exact_cmd,
+       "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+
+ALIAS (show_bgp_community_exact,
+       show_bgp_community2_exact_cmd,
+       "show bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+
+ALIAS (show_bgp_community_exact,
+       show_bgp_ipv6_community2_exact_cmd,
+       "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+
+ALIAS (show_bgp_community_exact,
+       show_bgp_community3_exact_cmd,
+       "show bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+
+ALIAS (show_bgp_community_exact,
+       show_bgp_ipv6_community3_exact_cmd,
+       "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+
+ALIAS (show_bgp_community_exact,
+       show_bgp_community4_exact_cmd,
+       "show bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+ 
+ALIAS (show_bgp_community_exact,
+       show_bgp_ipv6_community4_exact_cmd,
+       "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+
+/* old command */
+DEFUN (show_ipv6_bgp_community_exact,
+       show_ipv6_bgp_community_exact_cmd,
+       "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       IPV6_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+{
+  return bgp_show_community (vty, argc, argv, 1, AFI_IP6, SAFI_UNICAST);
+}
+
+/* old command */
+ALIAS (show_ipv6_bgp_community_exact,
+       show_ipv6_bgp_community2_exact_cmd,
+       "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       IPV6_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+
+/* old command */
+ALIAS (show_ipv6_bgp_community_exact,
+       show_ipv6_bgp_community3_exact_cmd,
+       "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       IPV6_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+
+/* old command */
+ALIAS (show_ipv6_bgp_community_exact,
+       show_ipv6_bgp_community4_exact_cmd,
+       "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       IPV6_STR
+       BGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+ 
+/* old command */
+DEFUN (show_ipv6_mbgp_community,
+       show_ipv6_mbgp_community_cmd,
+       "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       IPV6_STR
+       MBGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+{
+  return bgp_show_community (vty, argc, argv, 0, AFI_IP6, SAFI_MULTICAST);
+}
+
+/* old command */
+ALIAS (show_ipv6_mbgp_community,
+       show_ipv6_mbgp_community2_cmd,
+       "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       IPV6_STR
+       MBGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+
+/* old command */
+ALIAS (show_ipv6_mbgp_community,
+       show_ipv6_mbgp_community3_cmd,
+       "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       IPV6_STR
+       MBGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+
+/* old command */
+ALIAS (show_ipv6_mbgp_community,
+       show_ipv6_mbgp_community4_cmd,
+       "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
+       SHOW_STR
+       IPV6_STR
+       MBGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n")
+
+/* old command */
+DEFUN (show_ipv6_mbgp_community_exact,
+       show_ipv6_mbgp_community_exact_cmd,
+       "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       IPV6_STR
+       MBGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+{
+  return bgp_show_community (vty, argc, argv, 1, AFI_IP6, SAFI_MULTICAST);
+}
+
+/* old command */
+ALIAS (show_ipv6_mbgp_community_exact,
+       show_ipv6_mbgp_community2_exact_cmd,
+       "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       IPV6_STR
+       MBGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+
+/* old command */
+ALIAS (show_ipv6_mbgp_community_exact,
+       show_ipv6_mbgp_community3_exact_cmd,
+       "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       IPV6_STR
+       MBGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+
+/* old command */
+ALIAS (show_ipv6_mbgp_community_exact,
+       show_ipv6_mbgp_community4_exact_cmd,
+       "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
+       SHOW_STR
+       IPV6_STR
+       MBGP_STR
+       "Display routes matching the communities\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "community number\n"
+       "Do not send outside local AS (well-known community)\n"
+       "Do not advertise to any peer (well-known community)\n"
+       "Do not export to next AS (well-known community)\n"
+       "Exact match of the communities")
+#endif /* HAVE_IPV6 */
+
+int
+bgp_show_community_list (struct vty *vty, char *com, int exact,
+			 u_int16_t afi, u_char safi)
+{
+  struct community_list *list;
+
+  list = community_list_lookup (bgp_clist, com, COMMUNITY_LIST_AUTO);
+  if (list == NULL)
+    {
+      vty_out (vty, "%% %s is not a valid community-list name%s", com,
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  vty->output_arg = list;
+
+  if (exact)
+    return bgp_show (vty, NULL, afi, safi, bgp_show_type_community_list_exact);
+
+  return bgp_show (vty, NULL, afi, safi, bgp_show_type_community_list);
+}
+
+DEFUN (show_ip_bgp_community_list,
+       show_ip_bgp_community_list_cmd,
+       "show ip bgp community-list WORD",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display routes matching the community-list\n"
+       "community-list name\n")
+{
+  return bgp_show_community_list (vty, argv[0], 0, AFI_IP, SAFI_UNICAST);
+}
+
+DEFUN (show_ip_bgp_ipv4_community_list,
+       show_ip_bgp_ipv4_community_list_cmd,
+       "show ip bgp ipv4 (unicast|multicast) community-list WORD",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Display routes matching the community-list\n"
+       "community-list name\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_show_community_list (vty, argv[1], 0, AFI_IP, SAFI_MULTICAST);
+  
+  return bgp_show_community_list (vty, argv[1], 0, AFI_IP, SAFI_UNICAST);
+}
+
+DEFUN (show_ip_bgp_community_list_exact,
+       show_ip_bgp_community_list_exact_cmd,
+       "show ip bgp community-list WORD exact-match",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display routes matching the community-list\n"
+       "community-list name\n"
+       "Exact match of the communities\n")
+{
+  return bgp_show_community_list (vty, argv[0], 1, AFI_IP, SAFI_UNICAST);
+}
+
+DEFUN (show_ip_bgp_ipv4_community_list_exact,
+       show_ip_bgp_ipv4_community_list_exact_cmd,
+       "show ip bgp ipv4 (unicast|multicast) community-list WORD exact-match",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Display routes matching the community-list\n"
+       "community-list name\n"
+       "Exact match of the communities\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_show_community_list (vty, argv[1], 1, AFI_IP, SAFI_MULTICAST);
+ 
+  return bgp_show_community_list (vty, argv[1], 1, AFI_IP, SAFI_UNICAST);
+}
+
+#ifdef HAVE_IPV6
+DEFUN (show_bgp_community_list,
+       show_bgp_community_list_cmd,
+       "show bgp community-list WORD",
+       SHOW_STR
+       BGP_STR
+       "Display routes matching the community-list\n"
+       "community-list name\n")
+{
+  return bgp_show_community_list (vty, argv[0], 0, AFI_IP6, SAFI_UNICAST);
+}
+
+ALIAS (show_bgp_community_list,
+       show_bgp_ipv6_community_list_cmd,
+       "show bgp ipv6 community-list WORD",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Display routes matching the community-list\n"
+       "community-list name\n")
+
+/* old command */
+DEFUN (show_ipv6_bgp_community_list,
+       show_ipv6_bgp_community_list_cmd,
+       "show ipv6 bgp community-list WORD",
+       SHOW_STR
+       IPV6_STR
+       BGP_STR
+       "Display routes matching the community-list\n"
+       "community-list name\n")
+{
+  return bgp_show_community_list (vty, argv[0], 0, AFI_IP6, SAFI_UNICAST);
+}
+
+/* old command */
+DEFUN (show_ipv6_mbgp_community_list,
+       show_ipv6_mbgp_community_list_cmd,
+       "show ipv6 mbgp community-list WORD",
+       SHOW_STR
+       IPV6_STR
+       MBGP_STR
+       "Display routes matching the community-list\n"
+       "community-list name\n")
+{
+  return bgp_show_community_list (vty, argv[0], 0, AFI_IP6, SAFI_MULTICAST);
+}
+
+DEFUN (show_bgp_community_list_exact,
+       show_bgp_community_list_exact_cmd,
+       "show bgp community-list WORD exact-match",
+       SHOW_STR
+       BGP_STR
+       "Display routes matching the community-list\n"
+       "community-list name\n"
+       "Exact match of the communities\n")
+{
+  return bgp_show_community_list (vty, argv[0], 1, AFI_IP6, SAFI_UNICAST);
+}
+
+ALIAS (show_bgp_community_list_exact,
+       show_bgp_ipv6_community_list_exact_cmd,
+       "show bgp ipv6 community-list WORD exact-match",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Display routes matching the community-list\n"
+       "community-list name\n"
+       "Exact match of the communities\n")
+
+/* old command */
+DEFUN (show_ipv6_bgp_community_list_exact,
+       show_ipv6_bgp_community_list_exact_cmd,
+       "show ipv6 bgp community-list WORD exact-match",
+       SHOW_STR
+       IPV6_STR
+       BGP_STR
+       "Display routes matching the community-list\n"
+       "community-list name\n"
+       "Exact match of the communities\n")
+{
+  return bgp_show_community_list (vty, argv[0], 1, AFI_IP6, SAFI_UNICAST);
+}
+
+/* old command */
+DEFUN (show_ipv6_mbgp_community_list_exact,
+       show_ipv6_mbgp_community_list_exact_cmd,
+       "show ipv6 mbgp community-list WORD exact-match",
+       SHOW_STR
+       IPV6_STR
+       MBGP_STR
+       "Display routes matching the community-list\n"
+       "community-list name\n"
+       "Exact match of the communities\n")
+{
+  return bgp_show_community_list (vty, argv[0], 1, AFI_IP6, SAFI_MULTICAST);
+}
+#endif /* HAVE_IPV6 */
+
+void
+bgp_show_prefix_longer_clean (struct vty *vty)
+{
+  struct prefix *p;
+
+  p = vty->output_arg;
+  prefix_free (p);
+}
+
+int
+bgp_show_prefix_longer (struct vty *vty, char *prefix, afi_t afi,
+			safi_t safi, enum bgp_show_type type)
+{
+  int ret;
+  struct prefix *p;
+
+  p = prefix_new();
+
+  ret = str2prefix (prefix, p);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  vty->output_arg = p;
+  vty->output_clean = bgp_show_prefix_longer_clean;
+
+  return bgp_show (vty, NULL, afi, safi, type);
+}
+
+DEFUN (show_ip_bgp_prefix_longer,
+       show_ip_bgp_prefix_longer_cmd,
+       "show ip bgp A.B.C.D/M longer-prefixes",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+       "Display route and more specific routes\n")
+{
+  return bgp_show_prefix_longer (vty, argv[0], AFI_IP, SAFI_UNICAST,
+				 bgp_show_type_prefix_longer);
+}
+
+DEFUN (show_ip_bgp_flap_prefix_longer,
+       show_ip_bgp_flap_prefix_longer_cmd,
+       "show ip bgp flap-statistics A.B.C.D/M longer-prefixes",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display flap statistics of routes\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+       "Display route and more specific routes\n")
+{
+  return bgp_show_prefix_longer (vty, argv[0], AFI_IP, SAFI_UNICAST,
+				 bgp_show_type_flap_prefix_longer);
+}
+
+DEFUN (show_ip_bgp_ipv4_prefix_longer,
+       show_ip_bgp_ipv4_prefix_longer_cmd,
+       "show ip bgp ipv4 (unicast|multicast) A.B.C.D/M longer-prefixes",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+       "Display route and more specific routes\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_show_prefix_longer (vty, argv[1], AFI_IP, SAFI_MULTICAST,
+				   bgp_show_type_prefix_longer);
+
+  return bgp_show_prefix_longer (vty, argv[1], AFI_IP, SAFI_UNICAST,
+				 bgp_show_type_prefix_longer);
+}
+
+DEFUN (show_ip_bgp_flap_address,
+       show_ip_bgp_flap_address_cmd,
+       "show ip bgp flap-statistics A.B.C.D",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display flap statistics of routes\n"
+       "Network in the BGP routing table to display\n")
+{
+  return bgp_show_prefix_longer (vty, argv[0], AFI_IP, SAFI_UNICAST,
+				 bgp_show_type_flap_address);
+}
+
+DEFUN (show_ip_bgp_flap_prefix,
+       show_ip_bgp_flap_prefix_cmd,
+       "show ip bgp flap-statistics A.B.C.D/M",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display flap statistics of routes\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
+{
+  return bgp_show_prefix_longer (vty, argv[0], AFI_IP, SAFI_UNICAST,
+				 bgp_show_type_flap_prefix);
+}
+#ifdef HAVE_IPV6
+DEFUN (show_bgp_prefix_longer,
+       show_bgp_prefix_longer_cmd,
+       "show bgp X:X::X:X/M longer-prefixes",
+       SHOW_STR
+       BGP_STR
+       "IPv6 prefix <network>/<length>\n"
+       "Display route and more specific routes\n")
+{
+  return bgp_show_prefix_longer (vty, argv[0], AFI_IP6, SAFI_UNICAST,
+				 bgp_show_type_prefix_longer);
+}
+
+ALIAS (show_bgp_prefix_longer,
+       show_bgp_ipv6_prefix_longer_cmd,
+       "show bgp ipv6 X:X::X:X/M longer-prefixes",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "IPv6 prefix <network>/<length>\n"
+       "Display route and more specific routes\n")
+
+/* old command */
+DEFUN (show_ipv6_bgp_prefix_longer,
+       show_ipv6_bgp_prefix_longer_cmd,
+       "show ipv6 bgp X:X::X:X/M longer-prefixes",
+       SHOW_STR
+       IPV6_STR
+       BGP_STR
+       "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
+       "Display route and more specific routes\n")
+{
+  return bgp_show_prefix_longer (vty, argv[0], AFI_IP6, SAFI_UNICAST,
+				 bgp_show_type_prefix_longer);
+}
+
+/* old command */
+DEFUN (show_ipv6_mbgp_prefix_longer,
+       show_ipv6_mbgp_prefix_longer_cmd,
+       "show ipv6 mbgp X:X::X:X/M longer-prefixes",
+       SHOW_STR
+       IPV6_STR
+       MBGP_STR
+       "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
+       "Display route and more specific routes\n")
+{
+  return bgp_show_prefix_longer (vty, argv[0], AFI_IP6, SAFI_MULTICAST,
+				 bgp_show_type_prefix_longer);
+}
+#endif /* HAVE_IPV6 */
+
+void
+show_adj_route (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi,
+		int in)
+{
+  struct bgp_table *table;
+  struct bgp_adj_in *ain;
+  struct bgp_adj_out *adj;
+  unsigned long output_count;
+  struct bgp_node *rn;
+  int header1 = 1;
+  struct bgp *bgp;
+  int header2 = 1;
+
+  bgp = bgp_get_default ();
+
+  if (! bgp)
+    return;
+
+  table = bgp->rib[afi][safi];
+
+  output_count = 0;
+	
+  if (! in && CHECK_FLAG (peer->af_sflags[afi][safi],
+			  PEER_STATUS_DEFAULT_ORIGINATE))
+    {
+      vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE);
+      vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s", VTY_NEWLINE);
+      vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s", VTY_NEWLINE, VTY_NEWLINE);
+
+      vty_out (vty, "Originating default network 0.0.0.0%s%s",
+	       VTY_NEWLINE, VTY_NEWLINE);
+      header1 = 0;
+    }
+
+  for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
+    if (in)
+      {
+	for (ain = rn->adj_in; ain; ain = ain->next)
+	  if (ain->peer == peer)
+	    {
+	      if (header1)
+		{
+		  vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE);
+		  vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s", VTY_NEWLINE);
+		  vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s", VTY_NEWLINE, VTY_NEWLINE);
+		  header1 = 0;
+		}
+	      if (header2)
+		{
+		  vty_out (vty, BGP_SHOW_HEADER, VTY_NEWLINE);
+		  header2 = 0;
+		}
+	      if (ain->attr)
+		{ 
+		  route_vty_out_tmp (vty, &rn->p, ain->attr, safi);
+		  output_count++;
+		}
+	    }
+      }
+    else
+      {
+	for (adj = rn->adj_out; adj; adj = adj->next)
+	  if (adj->peer == peer)
+	    {
+	      if (header1)
+		{
+		  vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE);
+		  vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s", VTY_NEWLINE);
+		  vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s", VTY_NEWLINE, VTY_NEWLINE);
+		  header1 = 0;
+		}
+	      if (header2)
+		{
+		  vty_out (vty, BGP_SHOW_HEADER, VTY_NEWLINE);
+		  header2 = 0;
+		}
+	      if (adj->attr)
+		{	
+		  route_vty_out_tmp (vty, &rn->p, adj->attr, safi);
+		  output_count++;
+		}
+	    }
+      }
+  
+  if (output_count != 0)
+    vty_out (vty, "%sTotal number of prefixes %ld%s",
+	     VTY_NEWLINE, output_count, VTY_NEWLINE);
+}
+
+int
+peer_adj_routes (struct vty *vty, char *ip_str, afi_t afi, safi_t safi, int in)
+{
+  int ret;
+  struct peer *peer;
+  union sockunion su;
+
+  ret = str2sockunion (ip_str, &su);
+  if (ret < 0)
+    {
+      vty_out (vty, "Malformed address: %s%s", ip_str, VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  peer = peer_lookup (NULL, &su);
+  if (! peer || ! peer->afc[afi][safi])
+    {
+      vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (in && ! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
+    {
+      vty_out (vty, "%% Inbound soft reconfiguration not enabled%s",
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  show_adj_route (vty, peer, afi, safi, in);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_bgp_neighbor_advertised_route,
+       show_ip_bgp_neighbor_advertised_route_cmd,
+       "show ip bgp neighbors (A.B.C.D|X:X::X:X) advertised-routes",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display the routes advertised to a BGP neighbor\n")
+{
+  return peer_adj_routes (vty, argv[0], AFI_IP, SAFI_UNICAST, 0);
+}
+
+DEFUN (show_ip_bgp_ipv4_neighbor_advertised_route,
+       show_ip_bgp_ipv4_neighbor_advertised_route_cmd,
+       "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) advertised-routes",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display the routes advertised to a BGP neighbor\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return peer_adj_routes (vty, argv[1], AFI_IP, SAFI_MULTICAST, 0);
+
+  return peer_adj_routes (vty, argv[1], AFI_IP, SAFI_UNICAST, 0);
+}
+
+#ifdef HAVE_IPV6
+DEFUN (show_bgp_neighbor_advertised_route,
+       show_bgp_neighbor_advertised_route_cmd,
+       "show bgp neighbors (A.B.C.D|X:X::X:X) advertised-routes",
+       SHOW_STR
+       BGP_STR
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display the routes advertised to a BGP neighbor\n")
+{
+  return peer_adj_routes (vty, argv[0], AFI_IP6, SAFI_UNICAST, 0);
+}
+
+ALIAS (show_bgp_neighbor_advertised_route,
+       show_bgp_ipv6_neighbor_advertised_route_cmd,
+       "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) advertised-routes",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display the routes advertised to a BGP neighbor\n")
+
+/* old command */
+DEFUN (ipv6_bgp_neighbor_advertised_route,
+       ipv6_bgp_neighbor_advertised_route_cmd,
+       "show ipv6 bgp neighbors (A.B.C.D|X:X::X:X) advertised-routes",
+       SHOW_STR
+       IPV6_STR
+       BGP_STR
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display the routes advertised to a BGP neighbor\n")
+{
+  return peer_adj_routes (vty, argv[0], AFI_IP6, SAFI_UNICAST, 0);
+}
+
+/* old command */
+DEFUN (ipv6_mbgp_neighbor_advertised_route,
+       ipv6_mbgp_neighbor_advertised_route_cmd,
+       "show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X) advertised-routes",
+       SHOW_STR
+       IPV6_STR
+       MBGP_STR
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display the routes advertised to a BGP neighbor\n")
+{
+  return peer_adj_routes (vty, argv[0], AFI_IP6, SAFI_MULTICAST, 0);
+}
+#endif /* HAVE_IPV6 */
+
+DEFUN (show_ip_bgp_neighbor_received_routes,
+       show_ip_bgp_neighbor_received_routes_cmd,
+       "show ip bgp neighbors (A.B.C.D|X:X::X:X) received-routes",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display the received routes from neighbor\n")
+{
+  return peer_adj_routes (vty, argv[0], AFI_IP, SAFI_UNICAST, 1);
+}
+
+DEFUN (show_ip_bgp_ipv4_neighbor_received_routes,
+       show_ip_bgp_ipv4_neighbor_received_routes_cmd,
+       "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) received-routes",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display the received routes from neighbor\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return peer_adj_routes (vty, argv[1], AFI_IP, SAFI_MULTICAST, 1);
+
+  return peer_adj_routes (vty, argv[1], AFI_IP, SAFI_UNICAST, 1);
+}
+
+DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
+       show_ip_bgp_neighbor_received_prefix_filter_cmd,
+       "show ip bgp neighbors (A.B.C.D|X:X::X:X) received prefix-filter",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display information received from a BGP neighbor\n"
+       "Display the prefixlist filter\n")
+{
+  char name[BUFSIZ];
+  union sockunion *su;
+  struct peer *peer;
+  int count;
+
+  su = sockunion_str2su (argv[0]);
+  if (su == NULL)
+    return CMD_WARNING;
+
+  peer = peer_lookup (NULL, su);
+  if (! peer)
+    return CMD_WARNING;
+
+  sprintf (name, "%s.%d.%d", peer->host, AFI_IP, SAFI_UNICAST);
+  count =  prefix_bgp_show_prefix_list (NULL, AFI_IP, name);
+  if (count)
+    {
+      vty_out (vty, "Address family: IPv4 Unicast%s", VTY_NEWLINE);
+      prefix_bgp_show_prefix_list (vty, AFI_IP, name);
+    }
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_bgp_ipv4_neighbor_received_prefix_filter,
+       show_ip_bgp_ipv4_neighbor_received_prefix_filter_cmd,
+       "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) received prefix-filter",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display information received from a BGP neighbor\n"
+       "Display the prefixlist filter\n")
+{
+  char name[BUFSIZ];
+  union sockunion *su;
+  struct peer *peer;
+  int count;
+
+  su = sockunion_str2su (argv[1]);
+  if (su == NULL)
+    return CMD_WARNING;
+
+  peer = peer_lookup (NULL, su);
+  if (! peer)
+    return CMD_WARNING;
+
+  if (strncmp (argv[0], "m", 1) == 0)
+    {
+      sprintf (name, "%s.%d.%d", peer->host, AFI_IP, SAFI_MULTICAST);
+      count =  prefix_bgp_show_prefix_list (NULL, AFI_IP, name);
+      if (count)
+	{
+	  vty_out (vty, "Address family: IPv4 Multicast%s", VTY_NEWLINE);
+	  prefix_bgp_show_prefix_list (vty, AFI_IP, name);
+	}
+    }
+  else 
+    {
+      sprintf (name, "%s.%d.%d", peer->host, AFI_IP, SAFI_UNICAST);
+      count =  prefix_bgp_show_prefix_list (NULL, AFI_IP, name);
+      if (count)
+	{
+	  vty_out (vty, "Address family: IPv4 Unicast%s", VTY_NEWLINE);
+	  prefix_bgp_show_prefix_list (vty, AFI_IP, name);
+	}
+    }
+
+  return CMD_SUCCESS;
+}
+
+
+#ifdef HAVE_IPV6
+DEFUN (show_bgp_neighbor_received_routes,
+       show_bgp_neighbor_received_routes_cmd,
+       "show bgp neighbors (A.B.C.D|X:X::X:X) received-routes",
+       SHOW_STR
+       BGP_STR
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display the received routes from neighbor\n")
+{
+  return peer_adj_routes (vty, argv[0], AFI_IP6, SAFI_UNICAST, 1);
+}
+
+ALIAS (show_bgp_neighbor_received_routes,
+       show_bgp_ipv6_neighbor_received_routes_cmd,
+       "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) received-routes",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display the received routes from neighbor\n")
+
+DEFUN (show_bgp_neighbor_received_prefix_filter,
+       show_bgp_neighbor_received_prefix_filter_cmd,
+       "show bgp neighbors (A.B.C.D|X:X::X:X) received prefix-filter",
+       SHOW_STR
+       BGP_STR
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display information received from a BGP neighbor\n"
+       "Display the prefixlist filter\n")
+{
+  char name[BUFSIZ];
+  union sockunion *su;
+  struct peer *peer;
+  int count;
+
+  su = sockunion_str2su (argv[0]);
+  if (su == NULL)
+    return CMD_WARNING;
+
+  peer = peer_lookup (NULL, su);
+  if (! peer)
+    return CMD_WARNING;
+
+  sprintf (name, "%s.%d.%d", peer->host, AFI_IP6, SAFI_UNICAST);
+  count =  prefix_bgp_show_prefix_list (NULL, AFI_IP6, name);
+  if (count)
+    {
+      vty_out (vty, "Address family: IPv6 Unicast%s", VTY_NEWLINE);
+      prefix_bgp_show_prefix_list (vty, AFI_IP6, name);
+    }
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (show_bgp_neighbor_received_prefix_filter,
+       show_bgp_ipv6_neighbor_received_prefix_filter_cmd,
+       "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) received prefix-filter",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display information received from a BGP neighbor\n"
+       "Display the prefixlist filter\n")
+
+/* old command */
+DEFUN (ipv6_bgp_neighbor_received_routes,
+       ipv6_bgp_neighbor_received_routes_cmd,
+       "show ipv6 bgp neighbors (A.B.C.D|X:X::X:X) received-routes",
+       SHOW_STR
+       IPV6_STR
+       BGP_STR
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display the received routes from neighbor\n")
+{
+  return peer_adj_routes (vty, argv[0], AFI_IP6, SAFI_UNICAST, 1);
+}
+
+/* old command */
+DEFUN (ipv6_mbgp_neighbor_received_routes,
+       ipv6_mbgp_neighbor_received_routes_cmd,
+       "show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X) received-routes",
+       SHOW_STR
+       IPV6_STR
+       MBGP_STR
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display the received routes from neighbor\n")
+{
+  return peer_adj_routes (vty, argv[0], AFI_IP6, SAFI_MULTICAST, 1);
+}
+#endif /* HAVE_IPV6 */
+
+void
+bgp_show_neighbor_route_clean (struct vty *vty)
+{
+  union sockunion *su;
+
+  su = vty->output_arg;
+  XFREE (MTYPE_SOCKUNION, su);
+}
+
+int
+bgp_show_neighbor_route (struct vty *vty, char *ip_str, afi_t afi,
+			 safi_t safi, enum bgp_show_type type)
+{
+  union sockunion *su;
+  struct peer *peer;
+
+  su = sockunion_str2su (ip_str);
+  if (su == NULL)
+    {
+      vty_out (vty, "Malformed address: %s%s", ip_str, VTY_NEWLINE);
+	       return CMD_WARNING;
+    }
+
+  peer = peer_lookup (NULL, su);
+  if (! peer || ! peer->afc[afi][safi])
+    {
+      vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
+      XFREE (MTYPE_SOCKUNION, su);
+      return CMD_WARNING;
+    }
+ 
+  vty->output_arg = su;
+  vty->output_clean = bgp_show_neighbor_route_clean;
+
+  return bgp_show (vty, NULL, afi, safi, type);
+}
+
+DEFUN (show_ip_bgp_neighbor_routes,
+       show_ip_bgp_neighbor_routes_cmd,
+       "show ip bgp neighbors (A.B.C.D|X:X::X:X) routes",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display routes learned from neighbor\n")
+{
+  return bgp_show_neighbor_route (vty, argv[0], AFI_IP, SAFI_UNICAST,
+				  bgp_show_type_neighbor);
+}
+
+DEFUN (show_ip_bgp_neighbor_flap,
+       show_ip_bgp_neighbor_flap_cmd,
+       "show ip bgp neighbors (A.B.C.D|X:X::X:X) flap-statistics",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display flap statistics of the routes learned from neighbor\n")
+{
+  return bgp_show_neighbor_route (vty, argv[0], AFI_IP, SAFI_UNICAST,
+				  bgp_show_type_flap_neighbor);
+}
+
+DEFUN (show_ip_bgp_neighbor_damp,
+       show_ip_bgp_neighbor_damp_cmd,
+       "show ip bgp neighbors (A.B.C.D|X:X::X:X) dampened-routes",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display the dampened routes received from neighbor\n")
+{
+  return bgp_show_neighbor_route (vty, argv[0], AFI_IP, SAFI_UNICAST,
+				  bgp_show_type_damp_neighbor);
+}
+
+DEFUN (show_ip_bgp_ipv4_neighbor_routes,
+       show_ip_bgp_ipv4_neighbor_routes_cmd,
+       "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) routes",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display routes learned from neighbor\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_show_neighbor_route (vty, argv[1], AFI_IP, SAFI_MULTICAST,
+				    bgp_show_type_neighbor);
+
+  return bgp_show_neighbor_route (vty, argv[1], AFI_IP, SAFI_UNICAST,
+				  bgp_show_type_neighbor);
+}
+#ifdef HAVE_IPV6
+DEFUN (show_bgp_neighbor_routes,
+       show_bgp_neighbor_routes_cmd,
+       "show bgp neighbors (A.B.C.D|X:X::X:X) routes",
+       SHOW_STR
+       BGP_STR
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display routes learned from neighbor\n")
+{
+  return bgp_show_neighbor_route (vty, argv[0], AFI_IP6, SAFI_UNICAST,
+				  bgp_show_type_neighbor);
+}
+
+ALIAS (show_bgp_neighbor_routes,
+       show_bgp_ipv6_neighbor_routes_cmd,
+       "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X) routes",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display routes learned from neighbor\n")
+
+/* old command */
+DEFUN (ipv6_bgp_neighbor_routes,
+       ipv6_bgp_neighbor_routes_cmd,
+       "show ipv6 bgp neighbors (A.B.C.D|X:X::X:X) routes",
+       SHOW_STR
+       IPV6_STR
+       BGP_STR
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display routes learned from neighbor\n")
+{
+  return bgp_show_neighbor_route (vty, argv[0], AFI_IP6, SAFI_UNICAST,
+				  bgp_show_type_neighbor);
+}
+
+/* old command */
+DEFUN (ipv6_mbgp_neighbor_routes,
+       ipv6_mbgp_neighbor_routes_cmd,
+       "show ipv6 mbgp neighbors (A.B.C.D|X:X::X:X) routes",
+       SHOW_STR
+       IPV6_STR
+       MBGP_STR
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n"
+       "Display routes learned from neighbor\n")
+{
+  return bgp_show_neighbor_route (vty, argv[0], AFI_IP6, SAFI_MULTICAST,
+				  bgp_show_type_neighbor);
+}
+#endif /* HAVE_IPV6 */
+
+struct bgp_table *bgp_distance_table;
+
+struct bgp_distance
+{
+  /* Distance value for the IP source prefix. */
+  u_char distance;
+
+  /* Name of the access-list to be matched. */
+  char *access_list;
+};
+
+struct bgp_distance *
+bgp_distance_new ()
+{
+  struct bgp_distance *new;
+  new = XMALLOC (MTYPE_BGP_DISTANCE, sizeof (struct bgp_distance));
+  memset (new, 0, sizeof (struct bgp_distance));
+  return new;
+}
+
+void
+bgp_distance_free (struct bgp_distance *bdistance)
+{
+  XFREE (MTYPE_BGP_DISTANCE, bdistance);
+}
+
+int
+bgp_distance_set (struct vty *vty, char *distance_str, char *ip_str,
+		  char *access_list_str)
+{
+  int ret;
+  struct prefix_ipv4 p;
+  u_char distance;
+  struct bgp_node *rn;
+  struct bgp_distance *bdistance;
+
+  ret = str2prefix_ipv4 (ip_str, &p);
+  if (ret == 0)
+    {
+      vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  distance = atoi (distance_str);
+
+  /* Get BGP distance node. */
+  rn = bgp_node_get (bgp_distance_table, (struct prefix *) &p);
+  if (rn->info)
+    {
+      bdistance = rn->info;
+      bgp_unlock_node (rn);
+    }
+  else
+    {
+      bdistance = bgp_distance_new ();
+      rn->info = bdistance;
+    }
+
+  /* Set distance value. */
+  bdistance->distance = distance;
+
+  /* Reset access-list configuration. */
+  if (bdistance->access_list)
+    {
+      free (bdistance->access_list);
+      bdistance->access_list = NULL;
+    }
+  if (access_list_str)
+    bdistance->access_list = strdup (access_list_str);
+
+  return CMD_SUCCESS;
+}
+
+int
+bgp_distance_unset (struct vty *vty, char *distance_str, char *ip_str,
+		    char *access_list_str)
+{
+  int ret;
+  struct prefix_ipv4 p;
+  u_char distance;
+  struct bgp_node *rn;
+  struct bgp_distance *bdistance;
+
+  ret = str2prefix_ipv4 (ip_str, &p);
+  if (ret == 0)
+    {
+      vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  distance = atoi (distance_str);
+
+  rn = bgp_node_lookup (bgp_distance_table, (struct prefix *)&p);
+  if (! rn)
+    {
+      vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  bdistance = rn->info;
+
+  if (bdistance->access_list)
+    free (bdistance->access_list);
+  bgp_distance_free (bdistance);
+
+  rn->info = NULL;
+  bgp_unlock_node (rn);
+  bgp_unlock_node (rn);
+
+  return CMD_SUCCESS;
+}
+
+void
+bgp_distance_reset ()
+{
+  struct bgp_node *rn;
+  struct bgp_distance *bdistance;
+
+  for (rn = bgp_table_top (bgp_distance_table); rn; rn = bgp_route_next (rn))
+    if ((bdistance = rn->info) != NULL)
+      {
+	if (bdistance->access_list)
+	  free (bdistance->access_list);
+	bgp_distance_free (bdistance);
+	rn->info = NULL;
+	bgp_unlock_node (rn);
+      }
+}
+
+/* Apply BGP information to distance method. */
+u_char
+bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, struct bgp *bgp)
+{
+  struct bgp_node *rn;
+  struct prefix_ipv4 q;
+  struct peer *peer;
+  struct bgp_distance *bdistance;
+  struct access_list *alist;
+  struct bgp_static *bgp_static;
+
+  if (! bgp)
+    return 0;
+
+  if (p->family != AF_INET)
+    return 0;
+
+  peer = rinfo->peer;
+
+  if (peer->su.sa.sa_family != AF_INET)
+    return 0;
+
+  memset (&q, 0, sizeof (struct prefix_ipv4));
+  q.family = AF_INET;
+  q.prefix = peer->su.sin.sin_addr;
+  q.prefixlen = IPV4_MAX_BITLEN;
+
+  /* Check source address. */
+  rn = bgp_node_match (bgp_distance_table, (struct prefix *) &q);
+  if (rn)
+    {
+      bdistance = rn->info;
+      bgp_unlock_node (rn);
+
+      if (bdistance->access_list)
+	{
+	  alist = access_list_lookup (AFI_IP, bdistance->access_list);
+	  if (alist && access_list_apply (alist, p) == FILTER_PERMIT)
+	    return bdistance->distance;
+	}
+      else
+	return bdistance->distance;
+    }
+
+  /* Backdoor check. */
+  rn = bgp_node_lookup (bgp->route[AFI_IP][SAFI_UNICAST], p);
+  if (rn)
+    {
+      bgp_static = rn->info;
+      bgp_unlock_node (rn);
+
+      if (bgp_static->backdoor)
+	{
+	  if (bgp->distance_local)
+	    return bgp->distance_local;
+	  else
+	    return ZEBRA_IBGP_DISTANCE_DEFAULT;
+	}
+    }
+
+  if (peer_sort (peer) == BGP_PEER_EBGP)
+    {
+      if (bgp->distance_ebgp)
+	return bgp->distance_ebgp;
+      return ZEBRA_EBGP_DISTANCE_DEFAULT;
+    }
+  else
+    {
+      if (bgp->distance_ibgp)
+	return bgp->distance_ibgp;
+      return ZEBRA_IBGP_DISTANCE_DEFAULT;
+    }
+}
+
+DEFUN (bgp_distance,
+       bgp_distance_cmd,
+       "distance bgp <1-255> <1-255> <1-255>",
+       "Define an administrative distance\n"
+       "BGP distance\n"
+       "Distance for routes external to the AS\n"
+       "Distance for routes internal to the AS\n"
+       "Distance for local routes\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+
+  bgp->distance_ebgp = atoi (argv[0]);
+  bgp->distance_ibgp = atoi (argv[1]);
+  bgp->distance_local = atoi (argv[2]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_distance,
+       no_bgp_distance_cmd,
+       "no distance bgp <1-255> <1-255> <1-255>",
+       NO_STR
+       "Define an administrative distance\n"
+       "BGP distance\n"
+       "Distance for routes external to the AS\n"
+       "Distance for routes internal to the AS\n"
+       "Distance for local routes\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+
+  bgp->distance_ebgp= 0;
+  bgp->distance_ibgp = 0;
+  bgp->distance_local = 0;
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_bgp_distance,
+       no_bgp_distance2_cmd,
+       "no distance bgp",
+       NO_STR
+       "Define an administrative distance\n"
+       "BGP distance\n")
+
+DEFUN (bgp_distance_source,
+       bgp_distance_source_cmd,
+       "distance <1-255> A.B.C.D/M",
+       "Define an administrative distance\n"
+       "Administrative distance\n"
+       "IP source prefix\n")
+{
+  bgp_distance_set (vty, argv[0], argv[1], NULL);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_distance_source,
+       no_bgp_distance_source_cmd,
+       "no distance <1-255> A.B.C.D/M",
+       NO_STR
+       "Define an administrative distance\n"
+       "Administrative distance\n"
+       "IP source prefix\n")
+{
+  bgp_distance_unset (vty, argv[0], argv[1], NULL);
+  return CMD_SUCCESS;
+}
+
+DEFUN (bgp_distance_source_access_list,
+       bgp_distance_source_access_list_cmd,
+       "distance <1-255> A.B.C.D/M WORD",
+       "Define an administrative distance\n"
+       "Administrative distance\n"
+       "IP source prefix\n"
+       "Access list name\n")
+{
+  bgp_distance_set (vty, argv[0], argv[1], argv[2]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_distance_source_access_list,
+       no_bgp_distance_source_access_list_cmd,
+       "no distance <1-255> A.B.C.D/M WORD",
+       NO_STR
+       "Define an administrative distance\n"
+       "Administrative distance\n"
+       "IP source prefix\n"
+       "Access list name\n")
+{
+  bgp_distance_unset (vty, argv[0], argv[1], argv[2]);
+  return CMD_SUCCESS;
+}
+
+DEFUN (bgp_damp_set,
+       bgp_damp_set_cmd,
+       "bgp dampening <1-45> <1-20000> <1-20000> <1-255>",
+       "BGP Specific commands\n"
+       "Enable route-flap dampening\n"
+       "Half-life time for the penalty\n"
+       "Value to start reusing a route\n"
+       "Value to start suppressing a route\n"
+       "Maximum duration to suppress a stable route\n")
+{
+  struct bgp *bgp;
+  int half = DEFAULT_HALF_LIFE * 60;
+  int reuse = DEFAULT_REUSE;
+  int suppress = DEFAULT_SUPPRESS;
+  int max = 4 * half;
+
+  if (argc == 4)
+    {
+      half = atoi (argv[0]) * 60;
+      reuse = atoi (argv[1]);
+      suppress = atoi (argv[2]);
+      max = atoi (argv[3]) * 60;
+    }
+  else if (argc == 1)
+    {
+      half = atoi (argv[0]) * 60;
+      max = 4 * half;
+    }
+
+  bgp = vty->index;
+  return bgp_damp_enable (bgp, bgp_node_afi (vty), bgp_node_safi (vty),
+			  half, reuse, suppress, max);
+}
+
+ALIAS (bgp_damp_set,
+       bgp_damp_set2_cmd,
+       "bgp dampening <1-45>",
+       "BGP Specific commands\n"
+       "Enable route-flap dampening\n"
+       "Half-life time for the penalty\n")
+
+ALIAS (bgp_damp_set,
+       bgp_damp_set3_cmd,
+       "bgp dampening",
+       "BGP Specific commands\n"
+       "Enable route-flap dampening\n")
+
+DEFUN (bgp_damp_unset,
+       bgp_damp_unset_cmd,
+       "no bgp dampening",
+       NO_STR
+       "BGP Specific commands\n"
+       "Enable route-flap dampening\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  return bgp_damp_disable (bgp, bgp_node_afi (vty), bgp_node_safi (vty));
+}
+
+ALIAS (bgp_damp_unset,
+       bgp_damp_unset2_cmd,
+       "no bgp dampening <1-45> <1-20000> <1-20000> <1-255>",
+       NO_STR
+       "BGP Specific commands\n"
+       "Enable route-flap dampening\n"
+       "Half-life time for the penalty\n"
+       "Value to start reusing a route\n"
+       "Value to start suppressing a route\n"
+       "Maximum duration to suppress a stable route\n")
+
+DEFUN (show_ip_bgp_dampened_paths,
+       show_ip_bgp_dampened_paths_cmd,
+       "show ip bgp dampened-paths",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display paths suppressed due to dampening\n")
+{
+  return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, bgp_show_type_dampend_paths);
+}
+
+DEFUN (show_ip_bgp_flap_statistics,
+       show_ip_bgp_flap_statistics_cmd,
+       "show ip bgp flap-statistics",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display flap statistics of routes\n")
+{
+  return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, bgp_show_type_flap_statistics);
+}
+
+/* Display specified route of BGP table. */
+int
+bgp_clear_damp_route (struct vty *vty, char *view_name, char *ip_str,
+		      afi_t afi, safi_t safi, struct prefix_rd *prd,
+		      int prefix_check)
+{
+  int ret;
+  struct prefix match;
+  struct bgp_node *rn;
+  struct bgp_node *rm;
+  struct bgp_info *ri;
+  struct bgp_info *ri_temp;
+  struct bgp *bgp;
+  struct bgp_table *table;
+
+  /* BGP structure lookup. */
+  if (view_name)
+    {
+      bgp = bgp_lookup_by_name (view_name);
+      if (bgp == NULL)
+	{
+	  vty_out (vty, "%% Can't find BGP view %s%s", view_name, VTY_NEWLINE);
+	  return CMD_WARNING;
+	}
+    }
+  else
+    {
+      bgp = bgp_get_default ();
+      if (bgp == NULL)
+	{
+	  vty_out (vty, "%% No BGP process is configured%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	}
+    }
+
+  /* Check IP address argument. */
+  ret = str2prefix (ip_str, &match);
+  if (! ret)
+    {
+      vty_out (vty, "%% address is malformed%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  match.family = afi2family (afi);
+
+  if (safi == SAFI_MPLS_VPN)
+    {
+      for (rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_MPLS_VPN]); rn; rn = bgp_route_next (rn))
+        {
+          if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
+            continue;
+
+	  if ((table = rn->info) != NULL)
+	    if ((rm = bgp_node_match (table, &match)) != NULL)
+	      if (! prefix_check || rm->p.prefixlen == match.prefixlen)
+		{
+		  ri = rm->info;
+		  while (ri)
+		    {
+		      if (ri->damp_info)
+			{
+			  ri_temp = ri->next;
+			  bgp_damp_info_free (ri->damp_info, 1);
+			  ri = ri_temp;
+			}
+		      else
+			ri = ri->next;
+		    }
+		}
+        }
+    }
+  else
+    {
+      if ((rn = bgp_node_match (bgp->rib[afi][safi], &match)) != NULL)
+	if (! prefix_check || rn->p.prefixlen == match.prefixlen)
+	  {
+	    ri = rn->info;
+	    while (ri)
+	      {
+		if (ri->damp_info)
+		  {
+		    ri_temp = ri->next;
+		    bgp_damp_info_free (ri->damp_info, 1);
+		    ri = ri_temp;
+		  }
+		else
+		  ri = ri->next;
+	      }
+	  }
+    }
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (clear_ip_bgp_dampening,
+       clear_ip_bgp_dampening_cmd,
+       "clear ip bgp dampening",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear route flap dampening information\n")
+{
+  bgp_damp_info_clean ();
+  return CMD_SUCCESS;
+}
+
+DEFUN (clear_ip_bgp_dampening_prefix,
+       clear_ip_bgp_dampening_prefix_cmd,
+       "clear ip bgp dampening A.B.C.D/M",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear route flap dampening information\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
+{
+  return bgp_clear_damp_route (vty, NULL, argv[0], AFI_IP,
+			       SAFI_UNICAST, NULL, 1);
+}
+
+DEFUN (clear_ip_bgp_dampening_address,
+       clear_ip_bgp_dampening_address_cmd,
+       "clear ip bgp dampening A.B.C.D",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear route flap dampening information\n"
+       "Network to clear damping information\n")
+{
+  return bgp_clear_damp_route (vty, NULL, argv[0], AFI_IP,
+			       SAFI_UNICAST, NULL, 0);
+}
+
+DEFUN (clear_ip_bgp_dampening_address_mask,
+       clear_ip_bgp_dampening_address_mask_cmd,
+       "clear ip bgp dampening A.B.C.D A.B.C.D",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear route flap dampening information\n"
+       "Network to clear damping information\n"
+       "Network mask\n")
+{
+  int ret;
+  char prefix_str[BUFSIZ];
+
+  ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
+  if (! ret)
+    {
+      vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_clear_damp_route (vty, NULL, prefix_str, AFI_IP,
+			       SAFI_UNICAST, NULL, 0);
+}
+
+int
+bgp_config_write_network_vpnv4 (struct vty *vty, struct bgp *bgp,
+				afi_t afi, safi_t safi, int *write)
+{
+  struct bgp_node *prn;
+  struct bgp_node *rn;
+  struct bgp_table *table;
+  struct prefix *p;
+  struct prefix_rd *prd;
+  struct bgp_static *bgp_static;
+  u_int32_t label;
+  char buf[SU_ADDRSTRLEN];
+  char rdbuf[RD_ADDRSTRLEN];
+  
+  /* Network configuration. */
+  for (prn = bgp_table_top (bgp->route[afi][safi]); prn; prn = bgp_route_next (prn))
+    if ((table = prn->info) != NULL)
+      for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) 
+	if ((bgp_static = rn->info) != NULL)
+	  {
+	    p = &rn->p;
+	    prd = (struct prefix_rd *) &prn->p;
+
+	    /* "address-family" display.  */
+	    bgp_config_write_family_header (vty, afi, safi, write);
+
+	    /* "network" configuration display.  */
+	    prefix_rd2str (prd, rdbuf, RD_ADDRSTRLEN);
+	    label = decode_label (bgp_static->tag);
+
+	    vty_out (vty, " network %s/%d rd %s tag %d",
+		     inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), 
+		     p->prefixlen,
+		     rdbuf, label);
+	    vty_out (vty, "%s", VTY_NEWLINE);
+	  }
+  return 0;
+}
+
+/* Configuration of static route announcement and aggregate
+   information. */
+int
+bgp_config_write_network (struct vty *vty, struct bgp *bgp,
+			  afi_t afi, safi_t safi, int *write)
+{
+  struct bgp_node *rn;
+  struct prefix *p;
+  struct bgp_static *bgp_static;
+  struct bgp_aggregate *bgp_aggregate;
+  char buf[SU_ADDRSTRLEN];
+  
+  if (afi == AFI_IP && safi == SAFI_MPLS_VPN)
+    return bgp_config_write_network_vpnv4 (vty, bgp, afi, safi, write);
+
+  /* Network configuration. */
+  for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn)) 
+    if ((bgp_static = rn->info) != NULL)
+      {
+	p = &rn->p;
+
+	/* "address-family" display.  */
+	bgp_config_write_family_header (vty, afi, safi, write);
+
+	/* "network" configuration display.  */
+	if (bgp_option_check (BGP_OPT_CONFIG_CISCO) && afi == AFI_IP)
+	  {
+	    u_int32_t destination; 
+	    struct in_addr netmask;
+
+	    destination = ntohl (p->u.prefix4.s_addr);
+	    masklen2ip (p->prefixlen, &netmask);
+	    vty_out (vty, " network %s",
+		     inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN));
+
+	    if ((IN_CLASSC (destination) && p->prefixlen == 24)
+		|| (IN_CLASSB (destination) && p->prefixlen == 16)
+		|| (IN_CLASSA (destination) && p->prefixlen == 8)
+		|| p->u.prefix4.s_addr == 0)
+	      {
+		/* Natural mask is not display. */
+	      }
+	    else
+	      vty_out (vty, " mask %s", inet_ntoa (netmask));
+	  }
+	else
+	  {
+	    vty_out (vty, " network %s/%d",
+		     inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), 
+		     p->prefixlen);
+	  }
+
+	if (bgp_static->rmap.name)
+	  vty_out (vty, " route-map %s", bgp_static->rmap.name);
+	else if (bgp_static->backdoor)
+	  vty_out (vty, " backdoor");
+
+	vty_out (vty, "%s", VTY_NEWLINE);
+      }
+
+  /* Aggregate-address configuration. */
+  for (rn = bgp_table_top (bgp->aggregate[afi][safi]); rn; rn = bgp_route_next (rn))
+    if ((bgp_aggregate = rn->info) != NULL)
+      {
+	p = &rn->p;
+
+	/* "address-family" display.  */
+	bgp_config_write_family_header (vty, afi, safi, write);
+
+	if (bgp_option_check (BGP_OPT_CONFIG_CISCO) && afi == AFI_IP)
+	  {
+	    struct in_addr netmask;
+
+	    masklen2ip (p->prefixlen, &netmask);
+	    vty_out (vty, " aggregate-address %s %s",
+		     inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+		     inet_ntoa (netmask));
+	  }
+	else
+	  {
+	    vty_out (vty, " aggregate-address %s/%d",
+		     inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
+		     p->prefixlen);
+	  }
+
+	if (bgp_aggregate->as_set)
+	  vty_out (vty, " as-set");
+	
+	if (bgp_aggregate->summary_only)
+	  vty_out (vty, " summary-only");
+
+	vty_out (vty, "%s", VTY_NEWLINE);
+      }
+
+  return 0;
+}
+
+int
+bgp_config_write_distance (struct vty *vty, struct bgp *bgp)
+{
+  struct bgp_node *rn;
+  struct bgp_distance *bdistance;
+
+  /* Distance configuration. */
+  if (bgp->distance_ebgp
+      && bgp->distance_ibgp
+      && bgp->distance_local
+      && (bgp->distance_ebgp != ZEBRA_EBGP_DISTANCE_DEFAULT
+	  || bgp->distance_ibgp != ZEBRA_IBGP_DISTANCE_DEFAULT
+	  || bgp->distance_local != ZEBRA_IBGP_DISTANCE_DEFAULT))
+    vty_out (vty, " distance bgp %d %d %d%s",
+	     bgp->distance_ebgp, bgp->distance_ibgp, bgp->distance_local,
+	     VTY_NEWLINE);
+  
+  for (rn = bgp_table_top (bgp_distance_table); rn; rn = bgp_route_next (rn))
+    if ((bdistance = rn->info) != NULL)
+      {
+	vty_out (vty, " distance %d %s/%d %s%s", bdistance->distance,
+		 inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
+		 bdistance->access_list ? bdistance->access_list : "",
+		 VTY_NEWLINE);
+      }
+
+  return 0;
+}
+
+/* Allocate routing table structure and install commands. */
+void
+bgp_route_init ()
+{
+  /* Init BGP distance table. */
+  bgp_distance_table = bgp_table_init ();
+
+  /* IPv4 BGP commands. */
+  install_element (BGP_NODE, &bgp_network_cmd);
+  install_element (BGP_NODE, &bgp_network_mask_cmd);
+  install_element (BGP_NODE, &bgp_network_mask_natural_cmd);
+  install_element (BGP_NODE, &bgp_network_route_map_cmd);
+  install_element (BGP_NODE, &bgp_network_mask_route_map_cmd);
+  install_element (BGP_NODE, &bgp_network_mask_natural_route_map_cmd);
+  install_element (BGP_NODE, &bgp_network_backdoor_cmd);
+  install_element (BGP_NODE, &bgp_network_mask_backdoor_cmd);
+  install_element (BGP_NODE, &bgp_network_mask_natural_backdoor_cmd);
+  install_element (BGP_NODE, &no_bgp_network_cmd);
+  install_element (BGP_NODE, &no_bgp_network_mask_cmd);
+  install_element (BGP_NODE, &no_bgp_network_mask_natural_cmd);
+  install_element (BGP_NODE, &no_bgp_network_route_map_cmd);
+  install_element (BGP_NODE, &no_bgp_network_mask_route_map_cmd);
+  install_element (BGP_NODE, &no_bgp_network_mask_natural_route_map_cmd);
+  install_element (BGP_NODE, &no_bgp_network_backdoor_cmd);
+  install_element (BGP_NODE, &no_bgp_network_mask_backdoor_cmd);
+  install_element (BGP_NODE, &no_bgp_network_mask_natural_backdoor_cmd);
+
+  install_element (BGP_NODE, &aggregate_address_cmd);
+  install_element (BGP_NODE, &aggregate_address_mask_cmd);
+  install_element (BGP_NODE, &aggregate_address_summary_only_cmd);
+  install_element (BGP_NODE, &aggregate_address_mask_summary_only_cmd);
+  install_element (BGP_NODE, &aggregate_address_as_set_cmd);
+  install_element (BGP_NODE, &aggregate_address_mask_as_set_cmd);
+  install_element (BGP_NODE, &aggregate_address_as_set_summary_cmd);
+  install_element (BGP_NODE, &aggregate_address_mask_as_set_summary_cmd);
+  install_element (BGP_NODE, &aggregate_address_summary_as_set_cmd);
+  install_element (BGP_NODE, &aggregate_address_mask_summary_as_set_cmd);
+  install_element (BGP_NODE, &no_aggregate_address_cmd);
+  install_element (BGP_NODE, &no_aggregate_address_summary_only_cmd);
+  install_element (BGP_NODE, &no_aggregate_address_as_set_cmd);
+  install_element (BGP_NODE, &no_aggregate_address_as_set_summary_cmd);
+  install_element (BGP_NODE, &no_aggregate_address_summary_as_set_cmd);
+  install_element (BGP_NODE, &no_aggregate_address_mask_cmd);
+  install_element (BGP_NODE, &no_aggregate_address_mask_summary_only_cmd);
+  install_element (BGP_NODE, &no_aggregate_address_mask_as_set_cmd);
+  install_element (BGP_NODE, &no_aggregate_address_mask_as_set_summary_cmd);
+  install_element (BGP_NODE, &no_aggregate_address_mask_summary_as_set_cmd);
+
+  /* IPv4 unicast configuration.  */
+  install_element (BGP_IPV4_NODE, &bgp_network_cmd);
+  install_element (BGP_IPV4_NODE, &bgp_network_mask_cmd);
+  install_element (BGP_IPV4_NODE, &bgp_network_mask_natural_cmd);
+  install_element (BGP_IPV4_NODE, &bgp_network_route_map_cmd);
+  install_element (BGP_IPV4_NODE, &bgp_network_mask_route_map_cmd);
+  install_element (BGP_IPV4_NODE, &bgp_network_mask_natural_route_map_cmd);
+  install_element (BGP_IPV4_NODE, &no_bgp_network_cmd);
+  install_element (BGP_IPV4_NODE, &no_bgp_network_mask_cmd);
+  install_element (BGP_IPV4_NODE, &no_bgp_network_mask_natural_cmd);
+  install_element (BGP_IPV4_NODE, &no_bgp_network_route_map_cmd);
+  install_element (BGP_IPV4_NODE, &no_bgp_network_mask_route_map_cmd);
+  install_element (BGP_IPV4_NODE, &no_bgp_network_mask_natural_route_map_cmd);
+  install_element (BGP_IPV4_NODE, &aggregate_address_cmd);
+  install_element (BGP_IPV4_NODE, &aggregate_address_mask_cmd);
+  install_element (BGP_IPV4_NODE, &aggregate_address_summary_only_cmd);
+  install_element (BGP_IPV4_NODE, &aggregate_address_mask_summary_only_cmd);
+  install_element (BGP_IPV4_NODE, &aggregate_address_as_set_cmd);
+  install_element (BGP_IPV4_NODE, &aggregate_address_mask_as_set_cmd);
+  install_element (BGP_IPV4_NODE, &aggregate_address_as_set_summary_cmd);
+  install_element (BGP_IPV4_NODE, &aggregate_address_mask_as_set_summary_cmd);
+  install_element (BGP_IPV4_NODE, &aggregate_address_summary_as_set_cmd);
+  install_element (BGP_IPV4_NODE, &aggregate_address_mask_summary_as_set_cmd);
+  install_element (BGP_IPV4_NODE, &no_aggregate_address_cmd);
+  install_element (BGP_IPV4_NODE, &no_aggregate_address_summary_only_cmd);
+  install_element (BGP_IPV4_NODE, &no_aggregate_address_as_set_cmd);
+  install_element (BGP_IPV4_NODE, &no_aggregate_address_as_set_summary_cmd);
+  install_element (BGP_IPV4_NODE, &no_aggregate_address_summary_as_set_cmd);
+  install_element (BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
+  install_element (BGP_IPV4_NODE, &no_aggregate_address_mask_summary_only_cmd);
+  install_element (BGP_IPV4_NODE, &no_aggregate_address_mask_as_set_cmd);
+  install_element (BGP_IPV4_NODE, &no_aggregate_address_mask_as_set_summary_cmd);
+  install_element (BGP_IPV4_NODE, &no_aggregate_address_mask_summary_as_set_cmd);
+
+  /* IPv4 multicast configuration.  */
+  install_element (BGP_IPV4M_NODE, &bgp_network_cmd);
+  install_element (BGP_IPV4M_NODE, &bgp_network_mask_cmd);
+  install_element (BGP_IPV4M_NODE, &bgp_network_mask_natural_cmd);
+  install_element (BGP_IPV4M_NODE, &bgp_network_route_map_cmd);
+  install_element (BGP_IPV4M_NODE, &bgp_network_mask_route_map_cmd);
+  install_element (BGP_IPV4M_NODE, &bgp_network_mask_natural_route_map_cmd);
+  install_element (BGP_IPV4M_NODE, &no_bgp_network_cmd);
+  install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_cmd);
+  install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_natural_cmd);
+  install_element (BGP_IPV4M_NODE, &no_bgp_network_route_map_cmd);
+  install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_route_map_cmd);
+  install_element (BGP_IPV4M_NODE, &no_bgp_network_mask_natural_route_map_cmd);
+  install_element (BGP_IPV4M_NODE, &aggregate_address_cmd);
+  install_element (BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
+  install_element (BGP_IPV4M_NODE, &aggregate_address_summary_only_cmd);
+  install_element (BGP_IPV4M_NODE, &aggregate_address_mask_summary_only_cmd);
+  install_element (BGP_IPV4M_NODE, &aggregate_address_as_set_cmd);
+  install_element (BGP_IPV4M_NODE, &aggregate_address_mask_as_set_cmd);
+  install_element (BGP_IPV4M_NODE, &aggregate_address_as_set_summary_cmd);
+  install_element (BGP_IPV4M_NODE, &aggregate_address_mask_as_set_summary_cmd);
+  install_element (BGP_IPV4M_NODE, &aggregate_address_summary_as_set_cmd);
+  install_element (BGP_IPV4M_NODE, &aggregate_address_mask_summary_as_set_cmd);
+  install_element (BGP_IPV4M_NODE, &no_aggregate_address_cmd);
+  install_element (BGP_IPV4M_NODE, &no_aggregate_address_summary_only_cmd);
+  install_element (BGP_IPV4M_NODE, &no_aggregate_address_as_set_cmd);
+  install_element (BGP_IPV4M_NODE, &no_aggregate_address_as_set_summary_cmd);
+  install_element (BGP_IPV4M_NODE, &no_aggregate_address_summary_as_set_cmd);
+  install_element (BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
+  install_element (BGP_IPV4M_NODE, &no_aggregate_address_mask_summary_only_cmd);
+  install_element (BGP_IPV4M_NODE, &no_aggregate_address_mask_as_set_cmd);
+  install_element (BGP_IPV4M_NODE, &no_aggregate_address_mask_as_set_summary_cmd);
+  install_element (BGP_IPV4M_NODE, &no_aggregate_address_mask_summary_as_set_cmd);
+
+  install_element (VIEW_NODE, &show_ip_bgp_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_route_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_route_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_route_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_route_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_prefix_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_prefix_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_prefix_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_prefix_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_view_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_view_route_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_view_prefix_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_regexp_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_regexp_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_prefix_list_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_prefix_list_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_filter_list_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_filter_list_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_route_map_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_route_map_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_cidr_only_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_cidr_only_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_community_all_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_community_all_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_community_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_community2_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_community3_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_community4_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_community_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_community2_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_community3_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_community4_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_community_exact_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_community2_exact_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_community3_exact_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_community4_exact_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_community_exact_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_community2_exact_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_community3_exact_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_community4_exact_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_community_list_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_community_list_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_community_list_exact_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_community_list_exact_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_prefix_longer_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_prefix_longer_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_neighbor_advertised_route_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_advertised_route_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_routes_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_received_routes_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_routes_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_received_prefix_filter_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_dampened_paths_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_flap_statistics_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_flap_address_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_flap_prefix_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_flap_cidr_only_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_flap_regexp_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_flap_filter_list_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_flap_prefix_list_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_flap_prefix_longer_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_flap_route_map_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_neighbor_flap_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_neighbor_damp_cmd);
+
+  install_element (ENABLE_NODE, &show_ip_bgp_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_route_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_route_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_route_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_route_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_prefix_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_prefix_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_prefix_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_prefix_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_view_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_view_route_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_view_prefix_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_regexp_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_regexp_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_prefix_list_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_prefix_list_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_filter_list_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_filter_list_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_route_map_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_route_map_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_cidr_only_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_cidr_only_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_community_all_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community_all_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_community_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_community2_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_community3_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_community4_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community2_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community3_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community4_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_community_exact_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_community2_exact_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_community3_exact_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_community4_exact_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community_exact_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community2_exact_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community3_exact_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community4_exact_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_community_list_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community_list_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_community_list_exact_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community_list_exact_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_prefix_longer_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_prefix_longer_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_neighbor_advertised_route_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_advertised_route_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_neighbor_received_routes_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_received_routes_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_neighbor_routes_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_routes_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_received_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_dampened_paths_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_flap_statistics_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_flap_address_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_flap_prefix_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_flap_cidr_only_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_flap_regexp_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_flap_filter_list_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_flap_prefix_list_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_flap_prefix_longer_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_flap_route_map_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_neighbor_flap_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_neighbor_damp_cmd);
+
+ /* BGP dampening clear commands */
+  install_element (ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
+
+#ifdef HAVE_IPV6
+  /* New config IPv6 BGP commands.  */
+  install_element (BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
+  install_element (BGP_IPV6_NODE, &ipv6_bgp_network_route_map_cmd);
+  install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_cmd);
+  install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_route_map_cmd);
+
+  install_element (BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
+  install_element (BGP_IPV6_NODE, &ipv6_aggregate_address_summary_only_cmd);
+  install_element (BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
+  install_element (BGP_IPV6_NODE, &no_ipv6_aggregate_address_summary_only_cmd);
+
+  /* Old config IPv6 BGP commands.  */
+  install_element (BGP_NODE, &old_ipv6_bgp_network_cmd);
+  install_element (BGP_NODE, &old_no_ipv6_bgp_network_cmd);
+
+  install_element (BGP_NODE, &old_ipv6_aggregate_address_cmd);
+  install_element (BGP_NODE, &old_ipv6_aggregate_address_summary_only_cmd);
+  install_element (BGP_NODE, &old_no_ipv6_aggregate_address_cmd);
+  install_element (BGP_NODE, &old_no_ipv6_aggregate_address_summary_only_cmd);
+
+  install_element (VIEW_NODE, &show_bgp_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_cmd);
+  install_element (VIEW_NODE, &show_bgp_route_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_route_cmd);
+  install_element (VIEW_NODE, &show_bgp_prefix_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_prefix_cmd);
+  install_element (VIEW_NODE, &show_bgp_regexp_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_regexp_cmd);
+  install_element (VIEW_NODE, &show_bgp_prefix_list_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_prefix_list_cmd);
+  install_element (VIEW_NODE, &show_bgp_filter_list_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_filter_list_cmd);
+  install_element (VIEW_NODE, &show_bgp_route_map_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_route_map_cmd);
+  install_element (VIEW_NODE, &show_bgp_community_all_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_community_all_cmd);
+  install_element (VIEW_NODE, &show_bgp_community_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_community_cmd);
+  install_element (VIEW_NODE, &show_bgp_community2_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_community2_cmd);
+  install_element (VIEW_NODE, &show_bgp_community3_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_community3_cmd);
+  install_element (VIEW_NODE, &show_bgp_community4_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_community4_cmd);
+  install_element (VIEW_NODE, &show_bgp_community_exact_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_community_exact_cmd);
+  install_element (VIEW_NODE, &show_bgp_community2_exact_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_community2_exact_cmd);
+  install_element (VIEW_NODE, &show_bgp_community3_exact_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_community3_exact_cmd);
+  install_element (VIEW_NODE, &show_bgp_community4_exact_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_community4_exact_cmd);
+  install_element (VIEW_NODE, &show_bgp_community_list_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_community_list_cmd);
+  install_element (VIEW_NODE, &show_bgp_community_list_exact_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_community_list_exact_cmd);
+  install_element (VIEW_NODE, &show_bgp_prefix_longer_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_prefix_longer_cmd);
+  install_element (VIEW_NODE, &show_bgp_neighbor_advertised_route_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_advertised_route_cmd);
+  install_element (VIEW_NODE, &show_bgp_neighbor_received_routes_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_received_routes_cmd);
+  install_element (VIEW_NODE, &show_bgp_neighbor_routes_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_routes_cmd);
+  install_element (VIEW_NODE, &show_bgp_neighbor_received_prefix_filter_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_received_prefix_filter_cmd);
+
+  install_element (ENABLE_NODE, &show_bgp_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_cmd);
+  install_element (ENABLE_NODE, &show_bgp_route_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_route_cmd);
+  install_element (ENABLE_NODE, &show_bgp_prefix_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_prefix_cmd);
+  install_element (ENABLE_NODE, &show_bgp_regexp_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_regexp_cmd);
+  install_element (ENABLE_NODE, &show_bgp_prefix_list_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_prefix_list_cmd);
+  install_element (ENABLE_NODE, &show_bgp_filter_list_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_filter_list_cmd);
+  install_element (ENABLE_NODE, &show_bgp_route_map_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_route_map_cmd);
+  install_element (ENABLE_NODE, &show_bgp_community_all_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_community_all_cmd);
+  install_element (ENABLE_NODE, &show_bgp_community_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_community_cmd);
+  install_element (ENABLE_NODE, &show_bgp_community2_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_community2_cmd);
+  install_element (ENABLE_NODE, &show_bgp_community3_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_community3_cmd);
+  install_element (ENABLE_NODE, &show_bgp_community4_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_community4_cmd);
+  install_element (ENABLE_NODE, &show_bgp_community_exact_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_community_exact_cmd);
+  install_element (ENABLE_NODE, &show_bgp_community2_exact_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_community2_exact_cmd);
+  install_element (ENABLE_NODE, &show_bgp_community3_exact_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_community3_exact_cmd);
+  install_element (ENABLE_NODE, &show_bgp_community4_exact_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_community4_exact_cmd);
+  install_element (ENABLE_NODE, &show_bgp_community_list_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_community_list_cmd);
+  install_element (ENABLE_NODE, &show_bgp_community_list_exact_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_community_list_exact_cmd);
+  install_element (ENABLE_NODE, &show_bgp_prefix_longer_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_prefix_longer_cmd);
+  install_element (ENABLE_NODE, &show_bgp_neighbor_advertised_route_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_advertised_route_cmd);
+  install_element (ENABLE_NODE, &show_bgp_neighbor_received_routes_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_received_routes_cmd);
+  install_element (ENABLE_NODE, &show_bgp_neighbor_routes_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_routes_cmd);
+  install_element (ENABLE_NODE, &show_bgp_neighbor_received_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_received_prefix_filter_cmd);
+
+  /* old command */
+  install_element (VIEW_NODE, &show_ipv6_bgp_cmd);
+  install_element (VIEW_NODE, &show_ipv6_bgp_route_cmd);
+  install_element (VIEW_NODE, &show_ipv6_bgp_prefix_cmd);
+  install_element (VIEW_NODE, &show_ipv6_bgp_regexp_cmd);
+  install_element (VIEW_NODE, &show_ipv6_bgp_prefix_list_cmd);
+  install_element (VIEW_NODE, &show_ipv6_bgp_filter_list_cmd);
+  install_element (VIEW_NODE, &show_ipv6_bgp_community_all_cmd);
+  install_element (VIEW_NODE, &show_ipv6_bgp_community_cmd);
+  install_element (VIEW_NODE, &show_ipv6_bgp_community2_cmd);
+  install_element (VIEW_NODE, &show_ipv6_bgp_community3_cmd);
+  install_element (VIEW_NODE, &show_ipv6_bgp_community4_cmd);
+  install_element (VIEW_NODE, &show_ipv6_bgp_community_exact_cmd);
+  install_element (VIEW_NODE, &show_ipv6_bgp_community2_exact_cmd);
+  install_element (VIEW_NODE, &show_ipv6_bgp_community3_exact_cmd);
+  install_element (VIEW_NODE, &show_ipv6_bgp_community4_exact_cmd);
+  install_element (VIEW_NODE, &show_ipv6_bgp_community_list_cmd);
+  install_element (VIEW_NODE, &show_ipv6_bgp_community_list_exact_cmd);
+  install_element (VIEW_NODE, &show_ipv6_bgp_prefix_longer_cmd);
+  install_element (VIEW_NODE, &show_ipv6_mbgp_cmd);
+  install_element (VIEW_NODE, &show_ipv6_mbgp_route_cmd);
+  install_element (VIEW_NODE, &show_ipv6_mbgp_prefix_cmd);
+  install_element (VIEW_NODE, &show_ipv6_mbgp_regexp_cmd);
+  install_element (VIEW_NODE, &show_ipv6_mbgp_prefix_list_cmd);
+  install_element (VIEW_NODE, &show_ipv6_mbgp_filter_list_cmd);
+  install_element (VIEW_NODE, &show_ipv6_mbgp_community_all_cmd);
+  install_element (VIEW_NODE, &show_ipv6_mbgp_community_cmd);
+  install_element (VIEW_NODE, &show_ipv6_mbgp_community2_cmd);
+  install_element (VIEW_NODE, &show_ipv6_mbgp_community3_cmd);
+  install_element (VIEW_NODE, &show_ipv6_mbgp_community4_cmd);
+  install_element (VIEW_NODE, &show_ipv6_mbgp_community_exact_cmd);
+  install_element (VIEW_NODE, &show_ipv6_mbgp_community2_exact_cmd);
+  install_element (VIEW_NODE, &show_ipv6_mbgp_community3_exact_cmd);
+  install_element (VIEW_NODE, &show_ipv6_mbgp_community4_exact_cmd);
+  install_element (VIEW_NODE, &show_ipv6_mbgp_community_list_cmd);
+  install_element (VIEW_NODE, &show_ipv6_mbgp_community_list_exact_cmd);
+  install_element (VIEW_NODE, &show_ipv6_mbgp_prefix_longer_cmd);
+
+  /* old command */
+  install_element (ENABLE_NODE, &show_ipv6_bgp_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_bgp_route_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_bgp_prefix_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_bgp_regexp_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_bgp_prefix_list_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_bgp_filter_list_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_bgp_community_all_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_bgp_community_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_bgp_community2_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_bgp_community3_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_bgp_community4_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_bgp_community_exact_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_bgp_community2_exact_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_bgp_community3_exact_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_bgp_community4_exact_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_bgp_community_list_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_bgp_community_list_exact_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_bgp_prefix_longer_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_mbgp_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_mbgp_route_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_mbgp_prefix_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_mbgp_regexp_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_mbgp_prefix_list_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_mbgp_filter_list_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_mbgp_community_all_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_mbgp_community_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_mbgp_community2_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_mbgp_community3_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_mbgp_community4_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_mbgp_community_exact_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_mbgp_community2_exact_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_mbgp_community3_exact_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_mbgp_community4_exact_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_mbgp_community_list_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_mbgp_community_list_exact_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_mbgp_prefix_longer_cmd);
+
+  /* old command */
+  install_element (VIEW_NODE, &ipv6_bgp_neighbor_advertised_route_cmd);
+  install_element (ENABLE_NODE, &ipv6_bgp_neighbor_advertised_route_cmd);
+  install_element (VIEW_NODE, &ipv6_mbgp_neighbor_advertised_route_cmd);
+  install_element (ENABLE_NODE, &ipv6_mbgp_neighbor_advertised_route_cmd);
+
+  /* old command */
+  install_element (VIEW_NODE, &ipv6_bgp_neighbor_received_routes_cmd);
+  install_element (ENABLE_NODE, &ipv6_bgp_neighbor_received_routes_cmd);
+  install_element (VIEW_NODE, &ipv6_mbgp_neighbor_received_routes_cmd);
+  install_element (ENABLE_NODE, &ipv6_mbgp_neighbor_received_routes_cmd);
+
+  /* old command */
+  install_element (VIEW_NODE, &ipv6_bgp_neighbor_routes_cmd);
+  install_element (ENABLE_NODE, &ipv6_bgp_neighbor_routes_cmd);
+  install_element (VIEW_NODE, &ipv6_mbgp_neighbor_routes_cmd);
+  install_element (ENABLE_NODE, &ipv6_mbgp_neighbor_routes_cmd);
+#endif /* HAVE_IPV6 */
+
+  install_element (BGP_NODE, &bgp_distance_cmd);
+  install_element (BGP_NODE, &no_bgp_distance_cmd);
+  install_element (BGP_NODE, &no_bgp_distance2_cmd);
+  install_element (BGP_NODE, &bgp_distance_source_cmd);
+  install_element (BGP_NODE, &no_bgp_distance_source_cmd);
+  install_element (BGP_NODE, &bgp_distance_source_access_list_cmd);
+  install_element (BGP_NODE, &no_bgp_distance_source_access_list_cmd);
+
+  install_element (BGP_NODE, &bgp_damp_set_cmd);
+  install_element (BGP_NODE, &bgp_damp_set2_cmd);
+  install_element (BGP_NODE, &bgp_damp_set3_cmd);
+  install_element (BGP_NODE, &bgp_damp_unset_cmd);
+  install_element (BGP_NODE, &bgp_damp_unset2_cmd);
+  install_element (BGP_IPV4_NODE, &bgp_damp_set_cmd);
+  install_element (BGP_IPV4_NODE, &bgp_damp_set2_cmd);
+  install_element (BGP_IPV4_NODE, &bgp_damp_set3_cmd);
+  install_element (BGP_IPV4_NODE, &bgp_damp_unset_cmd);
+  install_element (BGP_IPV4_NODE, &bgp_damp_unset2_cmd);
+}
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
new file mode 100644
index 0000000..a11aa14
--- /dev/null
+++ b/bgpd/bgp_route.h
@@ -0,0 +1,159 @@
+/* BGP routing information base
+   Copyright (C) 1996, 97, 98, 2000 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+struct bgp_info
+{
+  /* For linked list. */
+  struct bgp_info *next;
+  struct bgp_info *prev;
+
+  /* BGP route type.  This can be static, RIP, OSPF, BGP etc.  */
+  u_char type;
+
+  /* When above type is BGP.  This sub type specify BGP sub type
+     information.  */
+  u_char sub_type;
+#define BGP_ROUTE_NORMAL       0
+#define BGP_ROUTE_STATIC       1
+#define BGP_ROUTE_AGGREGATE    2
+#define BGP_ROUTE_REDISTRIBUTE 3 
+
+  /* BGP information status.  */
+  u_char flags;
+#define BGP_INFO_IGP_CHANGED    (1 << 0)
+#define BGP_INFO_DAMPED         (1 << 1)
+#define BGP_INFO_HISTORY        (1 << 2)
+#define BGP_INFO_SELECTED       (1 << 3)
+#define BGP_INFO_VALID          (1 << 4)
+#define BGP_INFO_ATTR_CHANGED   (1 << 5)
+#define BGP_INFO_DMED_CHECK     (1 << 6)
+#define BGP_INFO_DMED_SELECTED  (1 << 7)
+
+  /* Peer structure.  */
+  struct peer *peer;
+
+  /* Attribute structure.  */
+  struct attr *attr;
+
+  /* This route is suppressed with aggregation.  */
+  int suppress;
+  
+  /* Nexthop reachability check.  */
+  u_int32_t igpmetric;
+
+  /* Uptime.  */
+  time_t uptime;
+
+  /* Pointer to dampening structure.  */
+  struct bgp_damp_info *damp_info;
+
+  /* MPLS label.  */
+  u_char tag[3];
+};
+
+/* BGP static route configuration. */
+struct bgp_static
+{
+  /* Backdoor configuration.  */
+  int backdoor;
+
+  /* Import check status.  */
+  u_char valid;
+
+  /* IGP metric. */
+  u_int32_t igpmetric;
+
+  /* IGP nexthop. */
+  struct in_addr igpnexthop;
+
+  /* BGP redistribute route-map.  */
+  struct
+  {
+    char *name;
+    struct route_map *map;
+  } rmap;
+
+  /* MPLS label.  */
+  u_char tag[3];
+};
+
+#define DISTRIBUTE_IN_NAME(F)   ((F)->dlist[FILTER_IN].name)
+#define DISTRIBUTE_IN(F)        ((F)->dlist[FILTER_IN].alist)
+#define DISTRIBUTE_OUT_NAME(F)  ((F)->dlist[FILTER_OUT].name)
+#define DISTRIBUTE_OUT(F)       ((F)->dlist[FILTER_OUT].alist)
+
+#define PREFIX_LIST_IN_NAME(F)  ((F)->plist[FILTER_IN].name)
+#define PREFIX_LIST_IN(F)       ((F)->plist[FILTER_IN].plist)
+#define PREFIX_LIST_OUT_NAME(F) ((F)->plist[FILTER_OUT].name)
+#define PREFIX_LIST_OUT(F)      ((F)->plist[FILTER_OUT].plist)
+
+#define FILTER_LIST_IN_NAME(F)  ((F)->aslist[FILTER_IN].name)
+#define FILTER_LIST_IN(F)       ((F)->aslist[FILTER_IN].aslist)
+#define FILTER_LIST_OUT_NAME(F) ((F)->aslist[FILTER_OUT].name)
+#define FILTER_LIST_OUT(F)      ((F)->aslist[FILTER_OUT].aslist)
+
+#define ROUTE_MAP_IN_NAME(F)    ((F)->map[FILTER_IN].name)
+#define ROUTE_MAP_IN(F)         ((F)->map[FILTER_IN].map)
+#define ROUTE_MAP_OUT_NAME(F)   ((F)->map[FILTER_OUT].name)
+#define ROUTE_MAP_OUT(F)        ((F)->map[FILTER_OUT].map)
+
+#define UNSUPPRESS_MAP_NAME(F)  ((F)->usmap.name)
+#define UNSUPPRESS_MAP(F)       ((F)->usmap.map)
+
+/* Prototypes. */
+void bgp_route_init ();
+void bgp_announce_route (struct peer *, afi_t, safi_t);
+void bgp_announce_route_all (struct peer *);
+void bgp_default_originate (struct peer *, afi_t, safi_t, int);
+void bgp_soft_reconfig_in (struct peer *, afi_t, safi_t);
+void bgp_clear_route (struct peer *, afi_t, safi_t);
+void bgp_clear_route_all (struct peer *);
+void bgp_clear_adj_in (struct peer *, afi_t, safi_t);
+
+int bgp_nlri_sanity_check (struct peer *, int, u_char *, bgp_size_t);
+int bgp_nlri_parse (struct peer *, struct attr *, struct bgp_nlri *);
+
+int bgp_maximum_prefix_overflow (struct peer *, afi_t, safi_t);
+
+void bgp_redistribute_add (struct prefix *, struct in_addr *, u_int32_t, u_char);
+void bgp_redistribute_delete (struct prefix *, u_char);
+void bgp_redistribute_withdraw (struct bgp *, afi_t, int);
+
+void bgp_static_delete (struct bgp *);
+void bgp_static_update (struct bgp *, struct prefix *, struct bgp_static *,
+			afi_t, safi_t);
+void bgp_static_withdraw (struct bgp *, struct prefix *, afi_t, safi_t);
+                     
+int bgp_static_set_vpnv4 (struct vty *vty, char *, char *, char *);
+
+int bgp_static_unset_vpnv4 (struct vty *, char *, char *, char *);
+
+int bgp_config_write_network (struct vty *, struct bgp *, afi_t, safi_t, int *);
+int bgp_config_write_distance (struct vty *, struct bgp *);
+
+void bgp_aggregate_increment (struct bgp *, struct prefix *, struct bgp_info *,
+			      afi_t, safi_t);
+void bgp_aggregate_decrement (struct bgp *, struct prefix *, struct bgp_info *,
+			      afi_t, safi_t);
+
+u_char bgp_distance_apply (struct prefix *, struct bgp_info *, struct bgp *);
+
+afi_t bgp_node_afi (struct vty *);
+safi_t bgp_node_safi (struct vty *);
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
new file mode 100644
index 0000000..498a600
--- /dev/null
+++ b/bgpd/bgp_routemap.c
@@ -0,0 +1,3207 @@
+/* Route map function of bgpd.
+   Copyright (C) 1998, 1999 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "prefix.h"
+#include "filter.h"
+#include "routemap.h"
+#include "command.h"
+#include "linklist.h"
+#include "plist.h"
+#include "memory.h"
+#include "log.h"
+#ifdef HAVE_GNU_REGEX
+#include <regex.h>
+#else
+#include "regex-gnu.h"
+#endif /* HAVE_GNU_REGEX */
+#include "buffer.h"
+#include "sockunion.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_table.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_aspath.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_regex.h"
+#include "bgpd/bgp_community.h"
+#include "bgpd/bgp_clist.h"
+#include "bgpd/bgp_filter.h"
+#include "bgpd/bgp_mplsvpn.h"
+#include "bgpd/bgp_ecommunity.h"
+
+/* Memo of route-map commands.
+
+o Cisco route-map
+
+ match as-path          :  Done
+       community        :  Done
+       interface        :  Not yet
+       ip address       :  Done
+       ip next-hop      :  Done
+       ip route-source  :  (This will not be implemented by bgpd)
+       ip prefix-list   :  Done
+       ipv6 address     :  Done
+       ipv6 next-hop    :  Done
+       ipv6 route-source:  (This will not be implemented by bgpd)
+       ipv6 prefix-list :  Done
+       length           :  (This will not be implemented by bgpd)
+       metric           :  Done
+       route-type       :  (This will not be implemented by bgpd)
+       tag              :  (This will not be implemented by bgpd)
+
+ set  as-path prepend   :  Done
+      as-path tag       :  Not yet
+      automatic-tag     :  (This will not be implemented by bgpd)
+      community         :  Done
+      comm-list         :  Not yet
+      dampning          :  Not yet
+      default           :  (This will not be implemented by bgpd)
+      interface         :  (This will not be implemented by bgpd)
+      ip default        :  (This will not be implemented by bgpd)
+      ip next-hop       :  Done
+      ip precedence     :  (This will not be implemented by bgpd)
+      ip tos            :  (This will not be implemented by bgpd)
+      level             :  (This will not be implemented by bgpd)
+      local-preference  :  Done
+      metric            :  Done
+      metric-type       :  Not yet
+      origin            :  Done
+      tag               :  (This will not be implemented by bgpd)
+      weight            :  Done
+
+o Local extention
+
+  set ipv6 next-hop global: Done
+  set ipv6 next-hop local : Done
+
+*/ 
+
+/* `match ip address IP_ACCESS_LIST' */
+
+/* Match function should return 1 if match is success else return
+   zero. */
+route_map_result_t
+route_match_ip_address (void *rule, struct prefix *prefix, 
+			route_map_object_t type, void *object)
+{
+  struct access_list *alist;
+  /* struct prefix_ipv4 match; */
+
+  if (type == RMAP_BGP)
+    {
+      alist = access_list_lookup (AFI_IP, (char *) rule);
+      if (alist == NULL)
+	return RMAP_NOMATCH;
+    
+      return (access_list_apply (alist, prefix) == FILTER_DENY ?
+	      RMAP_NOMATCH : RMAP_MATCH);
+    }
+  return RMAP_NOMATCH;
+}
+
+/* Route map `ip address' match statement.  `arg' should be
+   access-list name. */
+void *
+route_match_ip_address_compile (char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+/* Free route map's compiled `ip address' value. */
+void
+route_match_ip_address_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for ip address matching. */
+struct route_map_rule_cmd route_match_ip_address_cmd =
+{
+  "ip address",
+  route_match_ip_address,
+  route_match_ip_address_compile,
+  route_match_ip_address_free
+};
+
+/* `match ip next-hop IP_ADDRESS' */
+
+/* Match function return 1 if match is success else return zero. */
+route_map_result_t
+route_match_ip_next_hop (void *rule, struct prefix *prefix, 
+			 route_map_object_t type, void *object)
+{
+  struct access_list *alist;
+  struct bgp_info *bgp_info;
+  struct prefix_ipv4 p;
+
+  if (type == RMAP_BGP)
+    {
+      bgp_info = object;
+      p.family = AF_INET;
+      p.prefix = bgp_info->attr->nexthop;
+      p.prefixlen = IPV4_MAX_BITLEN;
+
+      alist = access_list_lookup (AFI_IP, (char *) rule);
+      if (alist == NULL)
+	return RMAP_NOMATCH;
+
+      return (access_list_apply (alist, &p) == FILTER_DENY ?
+              RMAP_NOMATCH : RMAP_MATCH);
+    }
+  return RMAP_NOMATCH;
+}
+
+/* Route map `ip next-hop' match statement. `arg' is
+   access-list name. */
+void *
+route_match_ip_next_hop_compile (char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+/* Free route map's compiled `ip address' value. */
+void
+route_match_ip_next_hop_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for ip next-hop matching. */
+struct route_map_rule_cmd route_match_ip_next_hop_cmd =
+{
+  "ip next-hop",
+  route_match_ip_next_hop,
+  route_match_ip_next_hop_compile,
+  route_match_ip_next_hop_free
+};
+
+/* `match ip address prefix-list PREFIX_LIST' */
+
+route_map_result_t
+route_match_ip_address_prefix_list (void *rule, struct prefix *prefix, 
+				    route_map_object_t type, void *object)
+{
+  struct prefix_list *plist;
+
+  if (type == RMAP_BGP)
+    {
+      plist = prefix_list_lookup (AFI_IP, (char *) rule);
+      if (plist == NULL)
+	return RMAP_NOMATCH;
+    
+      return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
+	      RMAP_NOMATCH : RMAP_MATCH);
+    }
+  return RMAP_NOMATCH;
+}
+
+void *
+route_match_ip_address_prefix_list_compile (char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+void
+route_match_ip_address_prefix_list_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd =
+{
+  "ip address prefix-list",
+  route_match_ip_address_prefix_list,
+  route_match_ip_address_prefix_list_compile,
+  route_match_ip_address_prefix_list_free
+};
+
+/* `match ip next-hop prefix-list PREFIX_LIST' */
+
+route_map_result_t
+route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix,
+                                    route_map_object_t type, void *object)
+{
+  struct prefix_list *plist;
+  struct bgp_info *bgp_info;
+  struct prefix_ipv4 p;
+
+  if (type == RMAP_BGP)
+    {
+      bgp_info = object;
+      p.family = AF_INET;
+      p.prefix = bgp_info->attr->nexthop;
+      p.prefixlen = IPV4_MAX_BITLEN;
+
+      plist = prefix_list_lookup (AFI_IP, (char *) rule);
+      if (plist == NULL)
+        return RMAP_NOMATCH;
+
+      return (prefix_list_apply (plist, &p) == PREFIX_DENY ?
+              RMAP_NOMATCH : RMAP_MATCH);
+    }
+  return RMAP_NOMATCH;
+}
+
+void *
+route_match_ip_next_hop_prefix_list_compile (char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+void
+route_match_ip_next_hop_prefix_list_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd =
+{
+  "ip next-hop prefix-list",
+  route_match_ip_next_hop_prefix_list,
+  route_match_ip_next_hop_prefix_list_compile,
+  route_match_ip_next_hop_prefix_list_free
+};
+
+/* `match metric METRIC' */
+
+/* Match function return 1 if match is success else return zero. */
+route_map_result_t
+route_match_metric (void *rule, struct prefix *prefix, 
+		    route_map_object_t type, void *object)
+{
+  u_int32_t *med;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      med = rule;
+      bgp_info = object;
+    
+      if (bgp_info->attr->med == *med)
+	return RMAP_MATCH;
+      else
+	return RMAP_NOMATCH;
+    }
+  return RMAP_NOMATCH;
+}
+
+/* Route map `match metric' match statement. `arg' is MED value */
+void *
+route_match_metric_compile (char *arg)
+{
+  u_int32_t *med;
+  char *endptr = NULL;
+
+  med = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
+  *med = strtoul (arg, &endptr, 10);
+  if (*endptr != '\0' || *med == ULONG_MAX)
+    {
+      XFREE (MTYPE_ROUTE_MAP_COMPILED, med);
+      return NULL;
+    }
+  return med;
+}
+
+/* Free route map's compiled `match metric' value. */
+void
+route_match_metric_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for metric matching. */
+struct route_map_rule_cmd route_match_metric_cmd =
+{
+  "metric",
+  route_match_metric,
+  route_match_metric_compile,
+  route_match_metric_free
+};
+
+/* `match as-path ASPATH' */
+
+/* Match function for as-path match.  I assume given object is */
+route_map_result_t
+route_match_aspath (void *rule, struct prefix *prefix, 
+		    route_map_object_t type, void *object)
+{
+  
+  struct as_list *as_list;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      as_list = as_list_lookup ((char *) rule);
+      if (as_list == NULL)
+	return RMAP_NOMATCH;
+    
+      bgp_info = object;
+    
+      /* Perform match. */
+      return ((as_list_apply (as_list, bgp_info->attr->aspath) == AS_FILTER_DENY) ? RMAP_NOMATCH : RMAP_MATCH);
+    }
+  return RMAP_NOMATCH;
+}
+
+/* Compile function for as-path match. */
+void *
+route_match_aspath_compile (char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+/* Compile function for as-path match. */
+void
+route_match_aspath_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for aspath matching. */
+struct route_map_rule_cmd route_match_aspath_cmd = 
+{
+  "as-path",
+  route_match_aspath,
+  route_match_aspath_compile,
+  route_match_aspath_free
+};
+
+#if ROUTE_MATCH_ASPATH_OLD
+/* `match as-path ASPATH' */
+
+/* Match function for as-path match.  I assume given object is */
+int
+route_match_aspath (void *rule, struct prefix *prefix, void *object)
+{
+  regex_t *regex;
+  struct bgp_info *bgp_info;
+
+  regex = rule;
+  bgp_info = object;
+  
+  /* Perform match. */
+  return bgp_regexec (regex, bgp_info->attr->aspath);
+}
+
+/* Compile function for as-path match. */
+void *
+route_match_aspath_compile (char *arg)
+{
+  regex_t *regex;
+
+  regex = bgp_regcomp (arg);
+  if (! regex)
+    return NULL;
+
+  return regex;
+}
+
+/* Compile function for as-path match. */
+void
+route_match_aspath_free (void *rule)
+{
+  regex_t *regex = rule;
+
+  bgp_regex_free (regex);
+}
+
+/* Route map commands for aspath matching. */
+struct route_map_rule_cmd route_match_aspath_cmd = 
+{
+  "as-path",
+  route_match_aspath,
+  route_match_aspath_compile,
+  route_match_aspath_free
+};
+#endif /* ROUTE_MATCH_ASPATH_OLD */
+
+/* `match community COMMUNIY' */
+struct rmap_community
+{
+  char *name;
+  int exact;
+};
+
+/* Match function for community match. */
+route_map_result_t
+route_match_community (void *rule, struct prefix *prefix, 
+		       route_map_object_t type, void *object)
+{
+  struct community_list *list;
+  struct bgp_info *bgp_info;
+  struct rmap_community *rcom;
+
+  if (type == RMAP_BGP) 
+    {
+      bgp_info = object;
+      rcom = rule;
+
+      list = community_list_lookup (bgp_clist, rcom->name, COMMUNITY_LIST_AUTO);
+      if (! list)
+	return RMAP_NOMATCH;
+
+      if (rcom->exact)
+	{
+	  if (community_list_exact_match (bgp_info->attr->community, list))
+	    return RMAP_MATCH;
+	}
+      else
+	{
+	  if (community_list_match (bgp_info->attr->community, list))
+	    return RMAP_MATCH;
+	}
+    }
+  return RMAP_NOMATCH;
+}
+
+/* Compile function for community match. */
+void *
+route_match_community_compile (char *arg)
+{
+  struct rmap_community *rcom;
+  int len;
+  char *p;
+
+  rcom = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_community));
+
+  p = strchr (arg, ' ');
+  if (p)
+    {
+      len = p - arg;
+      rcom->name = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, len + 1);
+      memcpy (rcom->name, arg, len);
+      rcom->exact = 1;
+    }
+  else
+    {
+      rcom->name = XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+      rcom->exact = 0;
+    }
+  return rcom;
+}
+
+/* Compile function for community match. */
+void
+route_match_community_free (void *rule)
+{
+  struct rmap_community *rcom = rule;
+
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rcom->name); 
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rcom);
+}
+
+/* Route map commands for community matching. */
+struct route_map_rule_cmd route_match_community_cmd = 
+{
+  "community",
+  route_match_community,
+  route_match_community_compile,
+  route_match_community_free
+};
+
+/* `match nlri` and `set nlri` are replaced by `address-family ipv4`
+   and `address-family vpnv4'.  */
+
+/* `match origin' */
+route_map_result_t
+route_match_origin (void *rule, struct prefix *prefix, 
+		    route_map_object_t type, void *object)
+{
+  u_char *origin;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      origin = rule;
+      bgp_info = object;
+    
+      if (bgp_info->attr->origin == *origin)
+	return RMAP_MATCH;
+    }
+
+  return RMAP_NOMATCH;
+}
+
+void *
+route_match_origin_compile (char *arg)
+{
+  u_char *origin;
+
+  origin = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_char));
+
+  if (strcmp (arg, "igp") == 0)
+    *origin = 0;
+  else if (strcmp (arg, "egp") == 0)
+    *origin = 1;
+  else
+    *origin = 2;
+
+  return origin;
+}
+
+/* Free route map's compiled `ip address' value. */
+void
+route_match_origin_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for origin matching. */
+struct route_map_rule_cmd route_match_origin_cmd =
+{
+  "origin",
+  route_match_origin,
+  route_match_origin_compile,
+  route_match_origin_free
+};
+/* `set ip next-hop IP_ADDRESS' */
+
+/* Set nexthop to object.  ojbect must be pointer to struct attr. */
+route_map_result_t
+route_set_ip_nexthop (void *rule, struct prefix *prefix,
+		      route_map_object_t type, void *object)
+{
+  struct in_addr *address;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      /* Fetch routemap's rule information. */
+      address = rule;
+      bgp_info = object;
+    
+      /* Set next hop value. */ 
+      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
+      bgp_info->attr->nexthop = *address;
+    }
+
+  return RMAP_OKAY;
+}
+
+/* Route map `ip nexthop' compile function.  Given string is converted
+   to struct in_addr structure. */
+void *
+route_set_ip_nexthop_compile (char *arg)
+{
+  int ret;
+  struct in_addr *address;
+
+  address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
+
+  ret = inet_aton (arg, address);
+
+  if (ret == 0)
+    {
+      XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
+      return NULL;
+    }
+
+  return address;
+}
+
+/* Free route map's compiled `ip nexthop' value. */
+void
+route_set_ip_nexthop_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for ip nexthop set. */
+struct route_map_rule_cmd route_set_ip_nexthop_cmd =
+{
+  "ip next-hop",
+  route_set_ip_nexthop,
+  route_set_ip_nexthop_compile,
+  route_set_ip_nexthop_free
+};
+
+/* `set local-preference LOCAL_PREF' */
+
+/* Set local preference. */
+route_map_result_t
+route_set_local_pref (void *rule, struct prefix *prefix,
+		      route_map_object_t type, void *object)
+{
+  u_int32_t *local_pref;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      /* Fetch routemap's rule information. */
+      local_pref = rule;
+      bgp_info = object;
+    
+      /* Set local preference value. */ 
+      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
+      bgp_info->attr->local_pref = *local_pref;
+    }
+
+  return RMAP_OKAY;
+}
+
+/* set local preference compilation. */
+void *
+route_set_local_pref_compile (char *arg)
+{
+  u_int32_t *local_pref;
+  char *endptr = NULL;
+
+  /* Local preference value shoud be integer. */
+  if (! all_digit (arg))
+    return NULL;
+
+  local_pref = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
+  *local_pref = strtoul (arg, &endptr, 10);
+  if (*endptr != '\0' || *local_pref == ULONG_MAX)
+    {
+      XFREE (MTYPE_ROUTE_MAP_COMPILED, local_pref);
+      return NULL;
+    }
+  return local_pref;
+}
+
+/* Free route map's local preference value. */
+void
+route_set_local_pref_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Set local preference rule structure. */
+struct route_map_rule_cmd route_set_local_pref_cmd = 
+{
+  "local-preference",
+  route_set_local_pref,
+  route_set_local_pref_compile,
+  route_set_local_pref_free,
+};
+
+/* `set weight WEIGHT' */
+
+/* Set weight. */
+route_map_result_t
+route_set_weight (void *rule, struct prefix *prefix, route_map_object_t type,
+		  void *object)
+{
+  u_int32_t *weight;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      /* Fetch routemap's rule information. */
+      weight = rule;
+      bgp_info = object;
+    
+      /* Set weight value. */ 
+      bgp_info->attr->weight = *weight;
+    }
+
+  return RMAP_OKAY;
+}
+
+/* set local preference compilation. */
+void *
+route_set_weight_compile (char *arg)
+{
+  u_int32_t *weight;
+  char *endptr = NULL;
+
+  /* Local preference value shoud be integer. */
+  if (! all_digit (arg))
+    return NULL;
+
+  weight = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
+  *weight = strtoul (arg, &endptr, 10);
+  if (*endptr != '\0' || *weight == ULONG_MAX)
+    {
+      XFREE (MTYPE_ROUTE_MAP_COMPILED, weight);
+      return NULL;
+    }
+  return weight;
+}
+
+/* Free route map's local preference value. */
+void
+route_set_weight_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Set local preference rule structure. */
+struct route_map_rule_cmd route_set_weight_cmd = 
+{
+  "weight",
+  route_set_weight,
+  route_set_weight_compile,
+  route_set_weight_free,
+};
+
+/* `set metric METRIC' */
+
+/* Set metric to attribute. */
+route_map_result_t
+route_set_metric (void *rule, struct prefix *prefix, 
+		  route_map_object_t type, void *object)
+{
+  char *metric;
+  u_int32_t metric_val;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      /* Fetch routemap's rule information. */
+      metric = rule;
+      bgp_info = object;
+
+      if (! (bgp_info->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)))
+	bgp_info->attr->med = 0;
+      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
+
+      if (all_digit (metric))
+	{
+	  metric_val = strtoul (metric, (char **)NULL, 10);
+	  bgp_info->attr->med = metric_val;
+	}
+      else
+	{
+	  metric_val = strtoul (metric+1, (char **)NULL, 10);
+
+	  if (strncmp (metric, "+", 1) == 0)
+	    {
+	      if (bgp_info->attr->med/2 + metric_val/2 > ULONG_MAX/2)
+		bgp_info->attr->med = ULONG_MAX-1;
+	      else
+		bgp_info->attr->med += metric_val;
+	    }
+	  else if (strncmp (metric, "-", 1) == 0)
+	    {
+	      if (bgp_info->attr->med <= metric_val) 
+		bgp_info->attr->med = 0;
+	      else
+		bgp_info->attr->med -= metric_val;
+	    }
+	}
+    }
+  return RMAP_OKAY;
+}
+
+/* set metric compilation. */
+void *
+route_set_metric_compile (char *arg)
+{
+  u_int32_t metric;
+  char *endptr = NULL;
+
+  if (all_digit (arg))
+    {
+      /* set metric value check*/
+      metric = strtoul (arg, &endptr, 10);
+      if (*endptr != '\0' || metric == ULONG_MAX)
+        return NULL;
+    }
+  else
+    {
+      /* set metric +/-value check */
+      if ((strncmp (arg, "+", 1) != 0
+	   && strncmp (arg, "-", 1) != 0)
+	   || (! all_digit (arg+1)))
+	return NULL;
+
+      metric = strtoul (arg+1, &endptr, 10);
+      if (*endptr != '\0' || metric == ULONG_MAX)
+	return NULL;
+    }
+
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+/* Free route map's compiled `set metric' value. */
+void
+route_set_metric_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Set metric rule structure. */
+struct route_map_rule_cmd route_set_metric_cmd = 
+{
+  "metric",
+  route_set_metric,
+  route_set_metric_compile,
+  route_set_metric_free,
+};
+
+/* `set as-path prepend ASPATH' */
+
+/* For AS path prepend mechanism. */
+route_map_result_t
+route_set_aspath_prepend (void *rule, struct prefix *prefix, route_map_object_t type, void *object)
+{
+  struct aspath *aspath;
+  struct aspath *new;
+  struct bgp_info *binfo;
+
+  if (type == RMAP_BGP)
+    {
+      aspath = rule;
+      binfo = object;
+    
+      if (binfo->attr->aspath->refcnt)
+	new = aspath_dup (binfo->attr->aspath);
+      else
+	new = binfo->attr->aspath;
+
+      aspath_prepend (aspath, new);
+      binfo->attr->aspath = new;
+    }
+
+  return RMAP_OKAY;
+}
+
+/* Compile function for as-path prepend. */
+void *
+route_set_aspath_prepend_compile (char *arg)
+{
+  struct aspath *aspath;
+
+  aspath = aspath_str2aspath (arg);
+  if (! aspath)
+    return NULL;
+  return aspath;
+}
+
+/* Compile function for as-path prepend. */
+void
+route_set_aspath_prepend_free (void *rule)
+{
+  struct aspath *aspath = rule;
+  aspath_free (aspath);
+}
+
+/* Set metric rule structure. */
+struct route_map_rule_cmd route_set_aspath_prepend_cmd = 
+{
+  "as-path prepend",
+  route_set_aspath_prepend,
+  route_set_aspath_prepend_compile,
+  route_set_aspath_prepend_free,
+};
+
+/* `set community COMMUNITY' */
+struct rmap_com_set
+{
+  struct community *com;
+  int additive;
+  int none;
+};
+
+/* For community set mechanism. */
+route_map_result_t
+route_set_community (void *rule, struct prefix *prefix,
+		     route_map_object_t type, void *object)
+{
+  struct rmap_com_set *rcs;
+  struct bgp_info *binfo;
+  struct attr *attr;
+  struct community *new = NULL;
+  struct community *old;
+  struct community *merge;
+
+  if (type == RMAP_BGP)
+    {
+      rcs = rule;
+      binfo = object;
+      attr = binfo->attr;
+      old = attr->community;
+
+      /* "none" case.  */
+      if (rcs->none)
+	{
+	  attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES));
+	  attr->community = NULL;
+	  return RMAP_OKAY;
+	}
+
+      /* "additive" case.  */
+      if (rcs->additive && old)
+	{
+	  merge = community_merge (community_dup (old), rcs->com);
+	  new = community_uniq_sort (merge);
+	  community_free (merge);
+	}
+      else
+	new = community_dup (rcs->com);
+
+      attr->community = new;
+      attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
+    }
+
+  return RMAP_OKAY;
+}
+
+/* Compile function for set community. */
+void *
+route_set_community_compile (char *arg)
+{
+  struct rmap_com_set *rcs;
+  struct community *com = NULL;
+  char *sp;
+  int additive = 0;
+  int none = 0;
+  
+  if (strcmp (arg, "none") == 0)
+    none = 1;
+  else
+    {
+      sp = strstr (arg, "additive");
+
+      if (sp && sp > arg)
+  	{
+	  /* "additive" keyworkd is included.  */
+	  additive = 1;
+	  *(sp - 1) = '\0';
+	}
+
+      com = community_str2com (arg);
+
+      if (additive)
+	*(sp - 1) = ' ';
+
+      if (! com)
+	return NULL;
+    }
+  
+  rcs = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct rmap_com_set));
+  memset (rcs, 0, sizeof (struct rmap_com_set));
+  
+  rcs->com = com;
+  rcs->additive = additive;
+  rcs->none = none;
+  
+  return rcs;
+}
+
+/* Free function for set community. */
+void
+route_set_community_free (void *rule)
+{
+  struct rmap_com_set *rcs = rule;
+
+  if (rcs->com)
+    community_free (rcs->com);
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rcs);
+}
+
+/* Set community rule structure. */
+struct route_map_rule_cmd route_set_community_cmd = 
+{
+  "community",
+  route_set_community,
+  route_set_community_compile,
+  route_set_community_free,
+};
+
+/* `set comm-list (<1-99>|<100-199>|WORD) delete' */
+
+/* For community set mechanism. */
+route_map_result_t
+route_set_community_delete (void *rule, struct prefix *prefix,
+			    route_map_object_t type, void *object)
+{
+  struct community_list *list;
+  struct community *merge;
+  struct community *new;
+  struct community *old;
+  struct bgp_info *binfo;
+
+  if (type == RMAP_BGP)
+    {
+      if (! rule)
+	return RMAP_OKAY;
+
+      binfo = object;
+      list = community_list_lookup (bgp_clist, rule, COMMUNITY_LIST_AUTO);
+      old = binfo->attr->community;
+
+      if (list && old)
+	{
+	  merge = community_list_match_delete (community_dup (old), list);
+	  new = community_uniq_sort (merge);
+	  community_free (merge);
+
+	  if (new->size == 0)
+	    {
+	      binfo->attr->community = NULL;
+	      binfo->attr->flag &= ~ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
+	      community_free (new);
+	    }
+	  else
+	    {
+	      binfo->attr->community = new;
+	      binfo->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
+	    }
+	}
+    }
+
+  return RMAP_OKAY;
+}
+
+/* Compile function for set community. */
+void *
+route_set_community_delete_compile (char *arg)
+{
+  char *p;
+  char *str;
+  int len;
+
+  p = strchr (arg, ' ');
+  if (p)
+    {
+      len = p - arg;
+      str = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, len + 1);
+      memcpy (str, arg, len);
+    }
+  else
+    str = NULL;
+
+  return str;
+}
+
+/* Free function for set community. */
+void
+route_set_community_delete_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Set community rule structure. */
+struct route_map_rule_cmd route_set_community_delete_cmd =
+{
+  "comm-list",
+  route_set_community_delete,
+  route_set_community_delete_compile,
+  route_set_community_delete_free,
+};
+
+/* `set extcommunity rt COMMUNITY' */
+
+/* For community set mechanism. */
+route_map_result_t
+route_set_ecommunity_rt (void *rule, struct prefix *prefix, 
+			 route_map_object_t type, void *object)
+{
+  struct ecommunity *ecom;
+  struct ecommunity *new_ecom;
+  struct ecommunity *old_ecom;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      ecom = rule;
+      bgp_info = object;
+    
+      if (! ecom)
+	return RMAP_OKAY;
+    
+      /* We assume additive for Extended Community. */
+      old_ecom = bgp_info->attr->ecommunity;
+
+      if (old_ecom)
+	new_ecom = ecommunity_merge (ecommunity_dup (old_ecom), ecom);
+      else
+	new_ecom = ecommunity_dup (ecom);
+
+      bgp_info->attr->ecommunity = new_ecom;
+
+      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
+    }
+  return RMAP_OKAY;
+}
+
+/* Compile function for set community. */
+void *
+route_set_ecommunity_rt_compile (char *arg)
+{
+  struct ecommunity *ecom;
+
+  ecom = ecommunity_str2com (arg, ECOMMUNITY_ROUTE_TARGET, 0);
+  if (! ecom)
+    return NULL;
+  return ecom;
+}
+
+/* Free function for set community. */
+void
+route_set_ecommunity_rt_free (void *rule)
+{
+  struct ecommunity *ecom = rule;
+  ecommunity_free (ecom);
+}
+
+/* Set community rule structure. */
+struct route_map_rule_cmd route_set_ecommunity_rt_cmd = 
+{
+  "extcommunity rt",
+  route_set_ecommunity_rt,
+  route_set_ecommunity_rt_compile,
+  route_set_ecommunity_rt_free,
+};
+
+/* `set extcommunity soo COMMUNITY' */
+
+/* For community set mechanism. */
+route_map_result_t
+route_set_ecommunity_soo (void *rule, struct prefix *prefix, 
+			 route_map_object_t type, void *object)
+{
+  struct ecommunity *ecom;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      ecom = rule;
+      bgp_info = object;
+    
+      if (! ecom)
+	return RMAP_OKAY;
+    
+      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES);
+      bgp_info->attr->ecommunity = ecommunity_dup (ecom);
+    }
+  return RMAP_OKAY;
+}
+
+/* Compile function for set community. */
+void *
+route_set_ecommunity_soo_compile (char *arg)
+{
+  struct ecommunity *ecom;
+
+  ecom = ecommunity_str2com (arg, ECOMMUNITY_SITE_ORIGIN, 0);
+  if (! ecom)
+    return NULL;
+  
+  return ecom;
+}
+
+/* Free function for set community. */
+void
+route_set_ecommunity_soo_free (void *rule)
+{
+  struct ecommunity *ecom = rule;
+  ecommunity_free (ecom);
+}
+
+/* Set community rule structure. */
+struct route_map_rule_cmd route_set_ecommunity_soo_cmd = 
+{
+  "extcommunity soo",
+  route_set_ecommunity_soo,
+  route_set_ecommunity_soo_compile,
+  route_set_ecommunity_soo_free,
+};
+
+/* `set origin ORIGIN' */
+
+/* For origin set. */
+route_map_result_t
+route_set_origin (void *rule, struct prefix *prefix, route_map_object_t type, void *object)
+{
+  u_char *origin;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      origin = rule;
+      bgp_info = object;
+    
+      bgp_info->attr->origin = *origin;
+    }
+
+  return RMAP_OKAY;
+}
+
+/* Compile function for origin set. */
+void *
+route_set_origin_compile (char *arg)
+{
+  u_char *origin;
+
+  origin = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_char));
+
+  if (strcmp (arg, "igp") == 0)
+    *origin = 0;
+  else if (strcmp (arg, "egp") == 0)
+    *origin = 1;
+  else
+    *origin = 2;
+
+  return origin;
+}
+
+/* Compile function for origin set. */
+void
+route_set_origin_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Set metric rule structure. */
+struct route_map_rule_cmd route_set_origin_cmd = 
+{
+  "origin",
+  route_set_origin,
+  route_set_origin_compile,
+  route_set_origin_free,
+};
+
+/* `set atomic-aggregate' */
+
+/* For atomic aggregate set. */
+route_map_result_t
+route_set_atomic_aggregate (void *rule, struct prefix *prefix,
+			    route_map_object_t type, void *object)
+{
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      bgp_info = object;
+      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
+    }
+
+  return RMAP_OKAY;
+}
+
+/* Compile function for atomic aggregate. */
+void *
+route_set_atomic_aggregate_compile (char *arg)
+{
+  return (void *)1;
+}
+
+/* Compile function for atomic aggregate. */
+void
+route_set_atomic_aggregate_free (void *rule)
+{
+  return;
+}
+
+/* Set atomic aggregate rule structure. */
+struct route_map_rule_cmd route_set_atomic_aggregate_cmd = 
+{
+  "atomic-aggregate",
+  route_set_atomic_aggregate,
+  route_set_atomic_aggregate_compile,
+  route_set_atomic_aggregate_free,
+};
+
+/* `set aggregator as AS A.B.C.D' */
+struct aggregator
+{
+  as_t as;
+  struct in_addr address;
+};
+
+route_map_result_t
+route_set_aggregator_as (void *rule, struct prefix *prefix, 
+			 route_map_object_t type, void *object)
+{
+  struct bgp_info *bgp_info;
+  struct aggregator *aggregator;
+
+  if (type == RMAP_BGP)
+    {
+      bgp_info = object;
+      aggregator = rule;
+    
+      bgp_info->attr->aggregator_as = aggregator->as;
+      bgp_info->attr->aggregator_addr = aggregator->address;
+      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR);
+    }
+
+  return RMAP_OKAY;
+}
+
+void *
+route_set_aggregator_as_compile (char *arg)
+{
+  struct aggregator *aggregator;
+  char as[10];
+  char address[20];
+
+  aggregator = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct aggregator));
+  memset (aggregator, 0, sizeof (struct aggregator));
+
+  sscanf (arg, "%s %s", as, address);
+
+  aggregator->as = strtoul (as, NULL, 10);
+  inet_aton (address, &aggregator->address);
+
+  return aggregator;
+}
+
+void
+route_set_aggregator_as_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd route_set_aggregator_as_cmd = 
+{
+  "aggregator as",
+  route_set_aggregator_as,
+  route_set_aggregator_as_compile,
+  route_set_aggregator_as_free,
+};
+
+#ifdef HAVE_IPV6
+/* `match ipv6 address IP_ACCESS_LIST' */
+
+route_map_result_t
+route_match_ipv6_address (void *rule, struct prefix *prefix, 
+			  route_map_object_t type, void *object)
+{
+  struct access_list *alist;
+
+  if (type == RMAP_BGP)
+    {
+      alist = access_list_lookup (AFI_IP6, (char *) rule);
+      if (alist == NULL)
+	return RMAP_NOMATCH;
+    
+      return (access_list_apply (alist, prefix) == FILTER_DENY ?
+	      RMAP_NOMATCH : RMAP_MATCH);
+    }
+  return RMAP_NOMATCH;
+}
+
+void *
+route_match_ipv6_address_compile (char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+void
+route_match_ipv6_address_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for ip address matching. */
+struct route_map_rule_cmd route_match_ipv6_address_cmd =
+{
+  "ipv6 address",
+  route_match_ipv6_address,
+  route_match_ipv6_address_compile,
+  route_match_ipv6_address_free
+};
+
+/* `match ipv6 next-hop IP_ADDRESS' */
+
+route_map_result_t
+route_match_ipv6_next_hop (void *rule, struct prefix *prefix, 
+			   route_map_object_t type, void *object)
+{
+  struct in6_addr *addr;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      addr = rule;
+      bgp_info = object;
+    
+      if (IPV6_ADDR_SAME (&bgp_info->attr->mp_nexthop_global, rule))
+	return RMAP_MATCH;
+
+      if (bgp_info->attr->mp_nexthop_len == 32 &&
+	  IPV6_ADDR_SAME (&bgp_info->attr->mp_nexthop_local, rule))
+	return RMAP_MATCH;
+
+      return RMAP_NOMATCH;
+    }
+
+  return RMAP_NOMATCH;
+}
+
+void *
+route_match_ipv6_next_hop_compile (char *arg)
+{
+  struct in6_addr *address;
+  int ret;
+
+  address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
+
+  ret = inet_pton (AF_INET6, arg, address);
+  if (!ret)
+    {
+      XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
+      return NULL;
+    }
+
+  return address;
+}
+
+void
+route_match_ipv6_next_hop_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd route_match_ipv6_next_hop_cmd =
+{
+  "ipv6 next-hop",
+  route_match_ipv6_next_hop,
+  route_match_ipv6_next_hop_compile,
+  route_match_ipv6_next_hop_free
+};
+
+/* `match ipv6 address prefix-list PREFIX_LIST' */
+
+route_map_result_t
+route_match_ipv6_address_prefix_list (void *rule, struct prefix *prefix, 
+			      route_map_object_t type, void *object)
+{
+  struct prefix_list *plist;
+
+  if (type == RMAP_BGP)
+    {
+      plist = prefix_list_lookup (AFI_IP6, (char *) rule);
+      if (plist == NULL)
+	return RMAP_NOMATCH;
+    
+      return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
+	      RMAP_NOMATCH : RMAP_MATCH);
+    }
+  return RMAP_NOMATCH;
+}
+
+void *
+route_match_ipv6_address_prefix_list_compile (char *arg)
+{
+  return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+void
+route_match_ipv6_address_prefix_list_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd =
+{
+  "ipv6 address prefix-list",
+  route_match_ipv6_address_prefix_list,
+  route_match_ipv6_address_prefix_list_compile,
+  route_match_ipv6_address_prefix_list_free
+};
+
+/* `set ipv6 nexthop global IP_ADDRESS' */
+
+/* Set nexthop to object.  ojbect must be pointer to struct attr. */
+route_map_result_t
+route_set_ipv6_nexthop_global (void *rule, struct prefix *prefix, 
+			       route_map_object_t type, void *object)
+{
+  struct in6_addr *address;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      /* Fetch routemap's rule information. */
+      address = rule;
+      bgp_info = object;
+    
+      /* Set next hop value. */ 
+      bgp_info->attr->mp_nexthop_global = *address;
+    
+      /* Set nexthop length. */
+      if (bgp_info->attr->mp_nexthop_len == 0)
+	bgp_info->attr->mp_nexthop_len = 16;
+    }
+
+  return RMAP_OKAY;
+}
+
+/* Route map `ip next-hop' compile function.  Given string is converted
+   to struct in_addr structure. */
+void *
+route_set_ipv6_nexthop_global_compile (char *arg)
+{
+  int ret;
+  struct in6_addr *address;
+
+  address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
+
+  ret = inet_pton (AF_INET6, arg, address);
+
+  if (ret == 0)
+    {
+      XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
+      return NULL;
+    }
+
+  return address;
+}
+
+/* Free route map's compiled `ip next-hop' value. */
+void
+route_set_ipv6_nexthop_global_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for ip nexthop set. */
+struct route_map_rule_cmd route_set_ipv6_nexthop_global_cmd =
+{
+  "ipv6 next-hop global",
+  route_set_ipv6_nexthop_global,
+  route_set_ipv6_nexthop_global_compile,
+  route_set_ipv6_nexthop_global_free
+};
+
+/* `set ipv6 nexthop local IP_ADDRESS' */
+
+/* Set nexthop to object.  ojbect must be pointer to struct attr. */
+route_map_result_t
+route_set_ipv6_nexthop_local (void *rule, struct prefix *prefix, 
+			      route_map_object_t type, void *object)
+{
+  struct in6_addr *address;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      /* Fetch routemap's rule information. */
+      address = rule;
+      bgp_info = object;
+    
+      /* Set next hop value. */ 
+      bgp_info->attr->mp_nexthop_local = *address;
+    
+      /* Set nexthop length. */
+      if (bgp_info->attr->mp_nexthop_len != 32)
+	bgp_info->attr->mp_nexthop_len = 32;
+    }
+
+  return RMAP_OKAY;
+}
+
+/* Route map `ip nexthop' compile function.  Given string is converted
+   to struct in_addr structure. */
+void *
+route_set_ipv6_nexthop_local_compile (char *arg)
+{
+  int ret;
+  struct in6_addr *address;
+
+  address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in6_addr));
+
+  ret = inet_pton (AF_INET6, arg, address);
+
+  if (ret == 0)
+    {
+      XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
+      return NULL;
+    }
+
+  return address;
+}
+
+/* Free route map's compiled `ip nexthop' value. */
+void
+route_set_ipv6_nexthop_local_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for ip nexthop set. */
+struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd =
+{
+  "ipv6 next-hop local",
+  route_set_ipv6_nexthop_local,
+  route_set_ipv6_nexthop_local_compile,
+  route_set_ipv6_nexthop_local_free
+};
+#endif /* HAVE_IPV6 */
+
+/* `set vpnv4 nexthop A.B.C.D' */
+
+route_map_result_t
+route_set_vpnv4_nexthop (void *rule, struct prefix *prefix, 
+			 route_map_object_t type, void *object)
+{
+  struct in_addr *address;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP)
+    {
+      /* Fetch routemap's rule information. */
+      address = rule;
+      bgp_info = object;
+    
+      /* Set next hop value. */ 
+      bgp_info->attr->mp_nexthop_global_in = *address;
+    }
+
+  return RMAP_OKAY;
+}
+
+void *
+route_set_vpnv4_nexthop_compile (char *arg)
+{
+  int ret;
+  struct in_addr *address;
+
+  address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
+
+  ret = inet_aton (arg, address);
+
+  if (ret == 0)
+    {
+      XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
+      return NULL;
+    }
+
+  return address;
+}
+
+void
+route_set_vpnv4_nexthop_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for ip nexthop set. */
+struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd =
+{
+  "vpnv4 next-hop",
+  route_set_vpnv4_nexthop,
+  route_set_vpnv4_nexthop_compile,
+  route_set_vpnv4_nexthop_free
+};
+
+/* `set originator-id' */
+
+/* For origin set. */
+route_map_result_t
+route_set_originator_id (void *rule, struct prefix *prefix, route_map_object_t type, void *object)
+{
+  struct in_addr *address;
+  struct bgp_info *bgp_info;
+
+  if (type == RMAP_BGP) 
+    {
+      address = rule;
+      bgp_info = object;
+    
+      bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID);
+      bgp_info->attr->originator_id = *address;
+    }
+
+  return RMAP_OKAY;
+}
+
+/* Compile function for originator-id set. */
+void *
+route_set_originator_id_compile (char *arg)
+{
+  int ret;
+  struct in_addr *address;
+
+  address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr));
+
+  ret = inet_aton (arg, address);
+
+  if (ret == 0)
+    {
+      XFREE (MTYPE_ROUTE_MAP_COMPILED, address);
+      return NULL;
+    }
+
+  return address;
+}
+
+/* Compile function for originator_id set. */
+void
+route_set_originator_id_free (void *rule)
+{
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Set metric rule structure. */
+struct route_map_rule_cmd route_set_originator_id_cmd = 
+{
+  "originator-id",
+  route_set_originator_id,
+  route_set_originator_id_compile,
+  route_set_originator_id_free,
+};
+
+/* Add bgp route map rule. */
+int
+bgp_route_match_add (struct vty *vty, struct route_map_index *index,
+		    char *command, char *arg)
+{
+  int ret;
+
+  ret = route_map_add_match (index, command, arg);
+  if (ret)
+    {
+      switch (ret)
+	{
+	case RMAP_RULE_MISSING:
+	  vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	  break;
+	case RMAP_COMPILE_ERROR:
+	  vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	  break;
+	}
+    }
+  return CMD_SUCCESS;
+}
+
+/* Delete bgp route map rule. */
+int
+bgp_route_match_delete (struct vty *vty, struct route_map_index *index,
+			char *command, char *arg)
+{
+  int ret;
+
+  ret = route_map_delete_match (index, command, arg);
+  if (ret)
+    {
+      switch (ret)
+	{
+	case RMAP_RULE_MISSING:
+	  vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	  break;
+	case RMAP_COMPILE_ERROR:
+	  vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	  break;
+	}
+    }
+  return CMD_SUCCESS;
+}
+
+/* Add bgp route map rule. */
+int
+bgp_route_set_add (struct vty *vty, struct route_map_index *index,
+		   char *command, char *arg)
+{
+  int ret;
+
+  ret = route_map_add_set (index, command, arg);
+  if (ret)
+    {
+      switch (ret)
+	{
+	case RMAP_RULE_MISSING:
+	  vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	  break;
+	case RMAP_COMPILE_ERROR:
+	  vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	  break;
+	}
+    }
+  return CMD_SUCCESS;
+}
+
+/* Delete bgp route map rule. */
+int
+bgp_route_set_delete (struct vty *vty, struct route_map_index *index,
+		      char *command, char *arg)
+{
+  int ret;
+
+  ret = route_map_delete_set (index, command, arg);
+  if (ret)
+    {
+      switch (ret)
+	{
+	case RMAP_RULE_MISSING:
+	  vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	  break;
+	case RMAP_COMPILE_ERROR:
+	  vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	  break;
+	}
+    }
+  return CMD_SUCCESS;
+}
+
+/* Hook function for updating route_map assignment. */
+void
+bgp_route_map_update ()
+{
+  int i;
+  afi_t afi;
+  safi_t safi;
+  int direct;
+  struct listnode *nn, *nm;
+  struct bgp *bgp;
+  struct peer *peer;
+  struct peer_group *group;
+  struct bgp_filter *filter;
+  struct bgp_node *bn;
+  struct bgp_static *bgp_static;
+
+  /* For neighbor route-map updates. */
+  LIST_LOOP (bm->bgp, bgp, nn)
+    {
+      LIST_LOOP (bgp->peer, peer, nm)
+	{
+	  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+	    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+	      {
+		filter = &peer->filter[afi][safi];
+	  
+		for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
+		  {
+		    if (filter->map[direct].name)
+		      filter->map[direct].map = 
+			route_map_lookup_by_name (filter->map[direct].name);
+		    else
+		      filter->map[direct].map = NULL;
+		  }
+
+		if (filter->usmap.name)
+		  filter->usmap.map = route_map_lookup_by_name (filter->usmap.name);
+		else
+		  filter->usmap.map = NULL;
+	      }
+	}
+      LIST_LOOP (bgp->group, group, nm)
+	{
+	  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+	    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+	      {
+		filter = &group->conf->filter[afi][safi];
+	  
+		for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
+		  {
+		    if (filter->map[direct].name)
+		      filter->map[direct].map = 
+			route_map_lookup_by_name (filter->map[direct].name);
+		    else
+		      filter->map[direct].map = NULL;
+		  }
+
+		if (filter->usmap.name)
+		  filter->usmap.map = route_map_lookup_by_name (filter->usmap.name);
+		else
+		  filter->usmap.map = NULL;
+	      }
+	}
+    }
+
+  /* For default-originate route-map updates. */
+  LIST_LOOP (bm->bgp, bgp, nn)
+    {
+      LIST_LOOP (bgp->peer, peer, nm)
+	{
+	  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+	    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+	      {
+		if (peer->default_rmap[afi][safi].name)
+		  peer->default_rmap[afi][safi].map =
+		    route_map_lookup_by_name (peer->default_rmap[afi][safi].name);
+		else
+		  peer->default_rmap[afi][safi].map = NULL;
+	      }
+	}
+    }
+
+  /* For network route-map updates. */
+  LIST_LOOP (bm->bgp, bgp, nn)
+    {
+      for (afi = AFI_IP; afi < AFI_MAX; afi++)
+	for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+	  for (bn = bgp_table_top (bgp->route[afi][safi]); bn;
+	       bn = bgp_route_next (bn))
+	    if ((bgp_static = bn->info) != NULL)
+	      {
+		if (bgp_static->rmap.name)
+		  bgp_static->rmap.map =
+			 route_map_lookup_by_name (bgp_static->rmap.name);
+		else
+		  bgp_static->rmap.map = NULL;
+	      }
+    }
+
+  /* For redistribute route-map updates. */
+  LIST_LOOP (bm->bgp, bgp, nn)
+    {
+      for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+	{
+	  if (bgp->rmap[ZEBRA_FAMILY_IPV4][i].name)
+	    bgp->rmap[ZEBRA_FAMILY_IPV4][i].map = 
+	      route_map_lookup_by_name (bgp->rmap[ZEBRA_FAMILY_IPV4][i].name);
+#ifdef HAVE_IPV6
+	  if (bgp->rmap[ZEBRA_FAMILY_IPV6][i].name)
+	    bgp->rmap[ZEBRA_FAMILY_IPV6][i].map =
+	      route_map_lookup_by_name (bgp->rmap[ZEBRA_FAMILY_IPV6][i].name);
+#endif /* HAVE_IPV6 */
+	}
+    }
+}
+
+DEFUN (match_ip_address, 
+       match_ip_address_cmd,
+       "match ip address (<1-199>|<1300-2699>|WORD)",
+       MATCH_STR
+       IP_STR
+       "Match address of route\n"
+       "IP access-list number\n"
+       "IP access-list number (expanded range)\n"
+       "IP Access-list name\n")
+{
+  return bgp_route_match_add (vty, vty->index, "ip address", argv[0]);
+}
+
+DEFUN (no_match_ip_address, 
+       no_match_ip_address_cmd,
+       "no match ip address",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match address of route\n")
+{
+  if (argc == 0)
+    return bgp_route_match_delete (vty, vty->index, "ip address", NULL);
+
+  return bgp_route_match_delete (vty, vty->index, "ip address", argv[0]);
+}
+
+ALIAS (no_match_ip_address, 
+       no_match_ip_address_val_cmd,
+       "no match ip address (<1-199>|<1300-2699>|WORD)",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match address of route\n"
+       "IP access-list number\n"
+       "IP access-list number (expanded range)\n"
+       "IP Access-list name\n")
+
+DEFUN (match_ip_next_hop, 
+       match_ip_next_hop_cmd,
+       "match ip next-hop (<1-199>|<1300-2699>|WORD)",
+       MATCH_STR
+       IP_STR
+       "Match next-hop address of route\n"
+       "IP access-list number\n"
+       "IP access-list number (expanded range)\n"
+       "IP Access-list name\n")
+{
+  return bgp_route_match_add (vty, vty->index, "ip next-hop", argv[0]);
+}
+
+DEFUN (no_match_ip_next_hop,
+       no_match_ip_next_hop_cmd,
+       "no match ip next-hop",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match next-hop address of route\n")
+{
+  if (argc == 0)
+    return bgp_route_match_delete (vty, vty->index, "ip next-hop", NULL);
+
+  return bgp_route_match_delete (vty, vty->index, "ip next-hop", argv[0]);
+}
+
+ALIAS (no_match_ip_next_hop,
+       no_match_ip_next_hop_val_cmd,
+       "no match ip next-hop (<1-199>|<1300-2699>|WORD)",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match next-hop address of route\n"
+       "IP access-list number\n"
+       "IP access-list number (expanded range)\n"
+       "IP Access-list name\n")
+
+DEFUN (match_ip_address_prefix_list, 
+       match_ip_address_prefix_list_cmd,
+       "match ip address prefix-list WORD",
+       MATCH_STR
+       IP_STR
+       "Match address of route\n"
+       "Match entries of prefix-lists\n"
+       "IP prefix-list name\n")
+{
+  return bgp_route_match_add (vty, vty->index, "ip address prefix-list", argv[0]);
+}
+
+DEFUN (no_match_ip_address_prefix_list,
+       no_match_ip_address_prefix_list_cmd,
+       "no match ip address prefix-list",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match address of route\n"
+       "Match entries of prefix-lists\n")
+{
+  if (argc == 0)
+    return bgp_route_match_delete (vty, vty->index, "ip address prefix-list", NULL);
+
+  return bgp_route_match_delete (vty, vty->index, "ip address prefix-list", argv[0]);
+}
+
+ALIAS (no_match_ip_address_prefix_list,
+       no_match_ip_address_prefix_list_val_cmd,
+       "no match ip address prefix-list WORD",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match address of route\n"
+       "Match entries of prefix-lists\n"
+       "IP prefix-list name\n")
+
+DEFUN (match_ip_next_hop_prefix_list, 
+       match_ip_next_hop_prefix_list_cmd,
+       "match ip next-hop prefix-list WORD",
+       MATCH_STR
+       IP_STR
+       "Match next-hop address of route\n"
+       "Match entries of prefix-lists\n"
+       "IP prefix-list name\n")
+{
+  return bgp_route_match_add (vty, vty->index, "ip next-hop prefix-list", argv[0]);
+}
+
+DEFUN (no_match_ip_next_hop_prefix_list,
+       no_match_ip_next_hop_prefix_list_cmd,
+       "no match ip next-hop prefix-list",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match next-hop address of route\n"
+       "Match entries of prefix-lists\n")
+{
+  if (argc == 0)
+    return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list", NULL);
+
+  return bgp_route_match_delete (vty, vty->index, "ip next-hop prefix-list", argv[0]);
+}
+
+ALIAS (no_match_ip_next_hop_prefix_list,
+       no_match_ip_next_hop_prefix_list_val_cmd,
+       "no match ip next-hop prefix-list WORD",
+       NO_STR
+       MATCH_STR
+       IP_STR
+       "Match next-hop address of route\n"
+       "Match entries of prefix-lists\n"
+       "IP prefix-list name\n")
+
+DEFUN (match_metric, 
+       match_metric_cmd,
+       "match metric <0-4294967295>",
+       MATCH_STR
+       "Match metric of route\n"
+       "Metric value\n")
+{
+  return bgp_route_match_add (vty, vty->index, "metric", argv[0]);
+}
+
+DEFUN (no_match_metric,
+       no_match_metric_cmd,
+       "no match metric",
+       NO_STR
+       MATCH_STR
+       "Match metric of route\n")
+{
+  if (argc == 0)
+    return bgp_route_match_delete (vty, vty->index, "metric", NULL);
+
+  return bgp_route_match_delete (vty, vty->index, "metric", argv[0]);
+}
+
+ALIAS (no_match_metric,
+       no_match_metric_val_cmd,
+       "no match metric <0-4294967295>",
+       NO_STR
+       MATCH_STR
+       "Match metric of route\n"
+       "Metric value\n")
+
+DEFUN (match_community, 
+       match_community_cmd,
+       "match community (<1-99>|<100-199>|WORD)",
+       MATCH_STR
+       "Match BGP community list\n"
+       "Community-list number (standard)\n"
+       "Community-list number (expanded)\n"
+       "Community-list name\n")
+{
+  return bgp_route_match_add (vty, vty->index, "community", argv[0]);
+}
+
+DEFUN (match_community_exact, 
+       match_community_exact_cmd,
+       "match community (<1-99>|<100-199>|WORD) exact-match",
+       MATCH_STR
+       "Match BGP community list\n"
+       "Community-list number (standard)\n"
+       "Community-list number (expanded)\n"
+       "Community-list name\n"
+       "Do exact matching of communities\n")
+{
+  int ret;
+  char *argstr;
+
+  argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
+		    strlen (argv[0]) + strlen ("exact-match") + 2);
+
+  sprintf (argstr, "%s exact-match", argv[0]);
+
+  ret = bgp_route_match_add (vty, vty->index, "community", argstr);
+
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
+
+  return ret;
+}
+
+DEFUN (no_match_community,
+       no_match_community_cmd,
+       "no match community",
+       NO_STR
+       MATCH_STR
+       "Match BGP community list\n")
+{
+  return bgp_route_match_delete (vty, vty->index, "community", NULL);
+}
+
+ALIAS (no_match_community,
+       no_match_community_val_cmd,
+       "no match community (<1-99>|<100-199>|WORD)",
+       NO_STR
+       MATCH_STR
+       "Match BGP community list\n"
+       "Community-list number (standard)\n"
+       "Community-list number (expanded)\n"
+       "Community-list name\n")
+
+ALIAS (no_match_community,
+       no_match_community_exact_cmd,
+       "no match community (<1-99>|<100-199>|WORD) exact-match",
+       NO_STR
+       MATCH_STR
+       "Match BGP community list\n"
+       "Community-list number (standard)\n"
+       "Community-list number (expanded)\n"
+       "Community-list name\n"
+       "Do exact matching of communities\n")
+
+DEFUN (match_aspath,
+       match_aspath_cmd,
+       "match as-path WORD",
+       MATCH_STR
+       "Match BGP AS path list\n"
+       "AS path access-list name\n")
+{
+  return bgp_route_match_add (vty, vty->index, "as-path", argv[0]);
+}
+
+DEFUN (no_match_aspath,
+       no_match_aspath_cmd,
+       "no match as-path",
+       NO_STR
+       MATCH_STR
+       "Match BGP AS path list\n")
+{
+  return bgp_route_match_delete (vty, vty->index, "as-path", NULL);
+}
+
+ALIAS (no_match_aspath,
+       no_match_aspath_val_cmd,
+       "no match as-path WORD",
+       NO_STR
+       MATCH_STR
+       "Match BGP AS path list\n"
+       "AS path access-list name\n")
+
+DEFUN (match_origin,
+       match_origin_cmd,
+       "match origin (egp|igp|incomplete)",
+       MATCH_STR
+       "BGP origin code\n"
+       "remote EGP\n"
+       "local IGP\n"
+       "unknown heritage\n")
+{
+  if (strncmp (argv[0], "igp", 2) == 0)
+    return bgp_route_match_add (vty, vty->index, "origin", "igp");
+  if (strncmp (argv[0], "egp", 1) == 0)
+    return bgp_route_match_add (vty, vty->index, "origin", "egp");
+  if (strncmp (argv[0], "incomplete", 2) == 0)
+    return bgp_route_match_add (vty, vty->index, "origin", "incomplete");
+
+  return CMD_WARNING;
+}
+
+DEFUN (no_match_origin,
+       no_match_origin_cmd,
+       "no match origin",
+       NO_STR
+       MATCH_STR
+       "BGP origin code\n")
+{
+  return bgp_route_match_delete (vty, vty->index, "origin", NULL);
+}
+
+ALIAS (no_match_origin,
+       no_match_origin_val_cmd,
+       "no match origin (egp|igp|incomplete)",
+       NO_STR
+       MATCH_STR
+       "BGP origin code\n"
+       "remote EGP\n"
+       "local IGP\n"
+       "unknown heritage\n")
+
+DEFUN (set_ip_nexthop,
+       set_ip_nexthop_cmd,
+       "set ip next-hop A.B.C.D",
+       SET_STR
+       IP_STR
+       "Next hop address\n"
+       "IP address of next hop\n")
+{
+  union sockunion su;
+  int ret;
+
+  ret = str2sockunion (argv[0], &su);
+  if (ret < 0)
+    {
+      vty_out (vty, "%% Malformed Next-hop address%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+ 
+  return bgp_route_set_add (vty, vty->index, "ip next-hop", argv[0]);
+}
+
+DEFUN (no_set_ip_nexthop,
+       no_set_ip_nexthop_cmd,
+       "no set ip next-hop",
+       NO_STR
+       SET_STR
+       IP_STR
+       "Next hop address\n")
+{
+  if (argc == 0)
+    return bgp_route_set_delete (vty, vty->index, "ip next-hop", NULL);
+
+  return bgp_route_set_delete (vty, vty->index, "ip next-hop", argv[0]);
+}
+
+ALIAS (no_set_ip_nexthop,
+       no_set_ip_nexthop_val_cmd,
+       "no set ip next-hop A.B.C.D",
+       NO_STR
+       SET_STR
+       IP_STR
+       "Next hop address\n"
+       "IP address of next hop\n")
+
+DEFUN (set_metric,
+       set_metric_cmd,
+       "set metric (<0-4294967295>|<+/-metric>)",
+       SET_STR
+       "Metric value for destination routing protocol\n"
+       "Metric value\n"
+       "Add or subtract metric\n")
+{
+  return bgp_route_set_add (vty, vty->index, "metric", argv[0]);
+}
+
+DEFUN (no_set_metric,
+       no_set_metric_cmd,
+       "no set metric",
+       NO_STR
+       SET_STR
+       "Metric value for destination routing protocol\n")
+{
+  if (argc == 0)
+    return bgp_route_set_delete (vty, vty->index, "metric", NULL);
+
+  return bgp_route_set_delete (vty, vty->index, "metric", argv[0]);
+}
+
+ALIAS (no_set_metric,
+       no_set_metric_val_cmd,
+       "no set metric <0-4294967295>",
+       NO_STR
+       SET_STR
+       "Metric value for destination routing protocol\n"
+       "Metric value\n")
+
+DEFUN (set_local_pref,
+       set_local_pref_cmd,
+       "set local-preference <0-4294967295>",
+       SET_STR
+       "BGP local preference path attribute\n"
+       "Preference value\n")
+{
+  return bgp_route_set_add (vty, vty->index, "local-preference", argv[0]);
+}
+
+DEFUN (no_set_local_pref,
+       no_set_local_pref_cmd,
+       "no set local-preference",
+       NO_STR
+       SET_STR
+       "BGP local preference path attribute\n")
+{
+  if (argc == 0)
+    return bgp_route_set_delete (vty, vty->index, "local-preference", NULL);
+
+  return bgp_route_set_delete (vty, vty->index, "local-preference", argv[0]);
+}
+
+ALIAS (no_set_local_pref,
+       no_set_local_pref_val_cmd,
+       "no set local-preference <0-4294967295>",
+       NO_STR
+       SET_STR
+       "BGP local preference path attribute\n"
+       "Preference value\n")
+
+DEFUN (set_weight,
+       set_weight_cmd,
+       "set weight <0-4294967295>",
+       SET_STR
+       "BGP weight for routing table\n"
+       "Weight value\n")
+{
+  return bgp_route_set_add (vty, vty->index, "weight", argv[0]);
+}
+
+DEFUN (no_set_weight,
+       no_set_weight_cmd,
+       "no set weight",
+       NO_STR
+       SET_STR
+       "BGP weight for routing table\n")
+{
+  if (argc == 0)
+    return bgp_route_set_delete (vty, vty->index, "weight", NULL);
+  
+  return bgp_route_set_delete (vty, vty->index, "weight", argv[0]);
+}
+
+ALIAS (no_set_weight,
+       no_set_weight_val_cmd,
+       "no set weight <0-4294967295>",
+       NO_STR
+       SET_STR
+       "BGP weight for routing table\n"
+       "Weight value\n")
+
+DEFUN (set_aspath_prepend,
+       set_aspath_prepend_cmd,
+       "set as-path prepend .<1-65535>",
+       SET_STR
+       "Prepend string for a BGP AS-path attribute\n"
+       "Prepend to the as-path\n"
+       "AS number\n")
+{
+  int ret;
+  char *str;
+
+  str = argv_concat (argv, argc, 0);
+  ret = bgp_route_set_add (vty, vty->index, "as-path prepend", str);
+  XFREE (MTYPE_TMP, str);
+
+  return ret;
+}
+
+DEFUN (no_set_aspath_prepend,
+       no_set_aspath_prepend_cmd,
+       "no set as-path prepend",
+       NO_STR
+       SET_STR
+       "Prepend string for a BGP AS-path attribute\n"
+       "Prepend to the as-path\n")
+{
+  return bgp_route_set_delete (vty, vty->index, "as-path prepend", NULL);
+}
+
+ALIAS (no_set_aspath_prepend,
+       no_set_aspath_prepend_val_cmd,
+       "no set as-path prepend .<1-65535>",
+       NO_STR
+       SET_STR
+       "Prepend string for a BGP AS-path attribute\n"
+       "Prepend to the as-path\n"
+       "AS number\n")
+
+DEFUN (set_community,
+       set_community_cmd,
+       "set community .AA:NN",
+       SET_STR
+       "BGP community attribute\n"
+       "Community number in aa:nn format or local-AS|no-advertise|no-export|internet or additive\n")
+{
+  int i;
+  int first = 0;
+  int additive = 0;
+  struct buffer *b;
+  struct community *com = NULL;
+  char *str;
+  char *argstr;
+  int ret;
+
+  b = buffer_new (1024);
+
+  for (i = 0; i < argc; i++)
+    {
+      if (strncmp (argv[i], "additive", strlen (argv[i])) == 0)
+ 	{
+ 	  additive = 1;
+ 	  continue;
+ 	}
+
+      if (first)
+	buffer_putc (b, ' ');
+      else
+	first = 1;
+
+      if (strncmp (argv[i], "internet", strlen (argv[i])) == 0)
+ 	{
+	  buffer_putstr (b, "internet");
+ 	  continue;
+ 	}
+      if (strncmp (argv[i], "local-AS", strlen (argv[i])) == 0)
+ 	{
+	  buffer_putstr (b, "local-AS");
+ 	  continue;
+ 	}
+      if (strncmp (argv[i], "no-a", strlen ("no-a")) == 0
+	  && strncmp (argv[i], "no-advertise", strlen (argv[i])) == 0)
+ 	{
+	  buffer_putstr (b, "no-advertise");
+ 	  continue;
+ 	}
+      if (strncmp (argv[i], "no-e", strlen ("no-e"))== 0
+	  && strncmp (argv[i], "no-export", strlen (argv[i])) == 0)
+ 	{
+	  buffer_putstr (b, "no-export");
+ 	  continue;
+ 	}
+      buffer_putstr (b, argv[i]);
+    }
+  buffer_putc (b, '\0');
+
+  /* Fetch result string then compile it to communities attribute.  */
+  str = buffer_getstr (b);
+  buffer_free (b);
+
+  if (str)
+    {
+      com = community_str2com (str);
+      free (str);
+    }
+
+  /* Can't compile user input into communities attribute.  */
+  if (! com)
+    {
+      vty_out (vty, "%% Malformed communities attribute%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Set communites attribute string.  */
+  str = community_str (com);
+
+  if (additive)
+    {
+      argstr = XCALLOC (MTYPE_TMP, strlen (str) + strlen (" additive") + 1);
+      strcpy (argstr, str);
+      strcpy (argstr + strlen (str), " additive");
+      ret =  bgp_route_set_add (vty, vty->index, "community", argstr);
+      XFREE (MTYPE_TMP, argstr);
+    }
+  else
+    ret =  bgp_route_set_add (vty, vty->index, "community", str);
+
+  community_free (com);
+
+  return ret;
+}
+
+DEFUN (set_community_none,
+       set_community_none_cmd,
+       "set community none",
+       SET_STR
+       "BGP community attribute\n"
+       "No community attribute\n")
+{
+  return bgp_route_set_add (vty, vty->index, "community", "none");
+}
+
+DEFUN (no_set_community,
+       no_set_community_cmd,
+       "no set community",
+       NO_STR
+       SET_STR
+       "BGP community attribute\n")
+{
+  return bgp_route_set_delete (vty, vty->index, "community", NULL);
+}
+
+ALIAS (no_set_community,
+       no_set_community_val_cmd,
+       "no set community .AA:NN",
+       NO_STR
+       SET_STR
+       "BGP community attribute\n"
+       "Community number in aa:nn format or local-AS|no-advertise|no-export|internet or additive\n")
+
+ALIAS (no_set_community,
+       no_set_community_none_cmd,
+       "no set community none",
+       NO_STR
+       SET_STR
+       "BGP community attribute\n"
+       "No community attribute\n")
+
+DEFUN (set_community_delete,
+       set_community_delete_cmd,
+       "set comm-list (<1-99>|<100-199>|WORD) delete",
+       SET_STR
+       "set BGP community list (for deletion)\n"
+       "Community-list number (standard)\n"
+       "Communitly-list number (expanded)\n"
+       "Community-list name\n"
+       "Delete matching communities\n")
+{
+  char *str;
+
+  str = XCALLOC (MTYPE_TMP, strlen (argv[0]) + strlen (" delete") + 1);
+  strcpy (str, argv[0]);
+  strcpy (str + strlen (argv[0]), " delete");
+
+  bgp_route_set_add (vty, vty->index, "comm-list", str);
+
+  XFREE (MTYPE_TMP, str);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_set_community_delete,
+       no_set_community_delete_cmd,
+       "no set comm-list",
+       NO_STR
+       SET_STR
+       "set BGP community list (for deletion)\n")
+{
+  return bgp_route_set_delete (vty, vty->index, "comm-list", NULL);
+}
+
+ALIAS (no_set_community_delete,
+       no_set_community_delete_val_cmd,
+       "no set comm-list (<1-99>|<100-199>|WORD) delete",
+       NO_STR
+       SET_STR
+       "set BGP community list (for deletion)\n"
+       "Community-list number (standard)\n"
+       "Communitly-list number (expanded)\n"
+       "Community-list name\n"
+       "Delete matching communities\n")
+
+DEFUN (set_ecommunity_rt,
+       set_ecommunity_rt_cmd,
+       "set extcommunity rt .ASN:nn_or_IP-address:nn",
+       SET_STR
+       "BGP extended community attribute\n"
+       "Route Target extened communityt\n"
+       "VPN extended community\n")
+{
+  int ret;
+  char *str;
+
+  str = argv_concat (argv, argc, 0);
+  ret = bgp_route_set_add (vty, vty->index, "extcommunity rt", str);
+  XFREE (MTYPE_TMP, str);
+
+  return ret;
+}
+
+DEFUN (no_set_ecommunity_rt,
+       no_set_ecommunity_rt_cmd,
+       "no set extcommunity rt",
+       NO_STR
+       SET_STR
+       "BGP extended community attribute\n"
+       "Route Target extened communityt\n")
+{
+  return bgp_route_set_delete (vty, vty->index, "extcommunity rt", NULL);
+}
+
+ALIAS (no_set_ecommunity_rt,
+       no_set_ecommunity_rt_val_cmd,
+       "no set extcommunity rt .ASN:nn_or_IP-address:nn",
+       NO_STR
+       SET_STR
+       "BGP extended community attribute\n"
+       "Route Target extened communityt\n"
+       "VPN extended community\n")
+
+DEFUN (set_ecommunity_soo,
+       set_ecommunity_soo_cmd,
+       "set extcommunity soo .ASN:nn_or_IP-address:nn",
+       SET_STR
+       "BGP extended community attribute\n"
+       "Site-of-Origin extended community\n"
+       "VPN extended community\n")
+{
+  int ret;
+  char *str;
+
+  str = argv_concat (argv, argc, 0);
+  ret = bgp_route_set_add (vty, vty->index, "extcommunity soo", str);
+  XFREE (MTYPE_TMP, str);
+  return ret;
+}
+
+DEFUN (no_set_ecommunity_soo,
+       no_set_ecommunity_soo_cmd,
+       "no set extcommunity soo",
+       NO_STR
+       SET_STR
+       "BGP extended community attribute\n"
+       "Site-of-Origin extended community\n")
+{
+  return bgp_route_set_delete (vty, vty->index, "extcommunity soo", NULL);
+}
+
+ALIAS (no_set_ecommunity_soo,
+       no_set_ecommunity_soo_val_cmd,
+       "no set extcommunity soo .ASN:nn_or_IP-address:nn",
+       NO_STR
+       SET_STR
+       "BGP extended community attribute\n"
+       "Site-of-Origin extended community\n"
+       "VPN extended community\n")
+
+DEFUN (set_origin,
+       set_origin_cmd,
+       "set origin (egp|igp|incomplete)",
+       SET_STR
+       "BGP origin code\n"
+       "remote EGP\n"
+       "local IGP\n"
+       "unknown heritage\n")
+{
+  if (strncmp (argv[0], "igp", 2) == 0)
+    return bgp_route_set_add (vty, vty->index, "origin", "igp");
+  if (strncmp (argv[0], "egp", 1) == 0)
+    return bgp_route_set_add (vty, vty->index, "origin", "egp");
+  if (strncmp (argv[0], "incomplete", 2) == 0)
+    return bgp_route_set_add (vty, vty->index, "origin", "incomplete");
+
+  return CMD_WARNING;
+}
+
+DEFUN (no_set_origin,
+       no_set_origin_cmd,
+       "no set origin",
+       NO_STR
+       SET_STR
+       "BGP origin code\n")
+{
+  return bgp_route_set_delete (vty, vty->index, "origin", NULL);
+}
+
+ALIAS (no_set_origin,
+       no_set_origin_val_cmd,
+       "no set origin (egp|igp|incomplete)",
+       NO_STR
+       SET_STR
+       "BGP origin code\n"
+       "remote EGP\n"
+       "local IGP\n"
+       "unknown heritage\n")
+
+DEFUN (set_atomic_aggregate,
+       set_atomic_aggregate_cmd,
+       "set atomic-aggregate",
+       SET_STR
+       "BGP atomic aggregate attribute\n" )
+{
+  return bgp_route_set_add (vty, vty->index, "atomic-aggregate", NULL);
+}
+
+DEFUN (no_set_atomic_aggregate,
+       no_set_atomic_aggregate_cmd,
+       "no set atomic-aggregate",
+       NO_STR
+       SET_STR
+       "BGP atomic aggregate attribute\n" )
+{
+  return bgp_route_set_delete (vty, vty->index, "atomic-aggregate", NULL);
+}
+
+DEFUN (set_aggregator_as,
+       set_aggregator_as_cmd,
+       "set aggregator as <1-65535> A.B.C.D",
+       SET_STR
+       "BGP aggregator attribute\n"
+       "AS number of aggregator\n"
+       "AS number\n"
+       "IP address of aggregator\n")
+{
+  int ret;
+  as_t as;
+  struct in_addr address;
+  char *endptr = NULL;
+  char *argstr;
+
+  as = strtoul (argv[0], &endptr, 10);
+  if (as == 0 || as == ULONG_MAX || *endptr != '\0')
+    {
+      vty_out (vty, "AS path value malformed%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ret = inet_aton (argv[1], &address);
+  if (ret == 0)
+    {
+      vty_out (vty, "Aggregator IP address is invalid%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
+		    strlen (argv[0]) + strlen (argv[1]) + 2);
+
+  sprintf (argstr, "%s %s", argv[0], argv[1]);
+
+  ret = bgp_route_set_add (vty, vty->index, "aggregator as", argstr);
+
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
+
+  return ret;
+}
+
+DEFUN (no_set_aggregator_as,
+       no_set_aggregator_as_cmd,
+       "no set aggregator as",
+       NO_STR
+       SET_STR
+       "BGP aggregator attribute\n"
+       "AS number of aggregator\n")
+{
+  int ret;
+  as_t as;
+  struct in_addr address;
+  char *endptr = NULL;
+  char *argstr;
+
+  if (argv == 0)
+    return bgp_route_set_delete (vty, vty->index, "aggregator as", NULL);
+  
+  as = strtoul (argv[0], &endptr, 10);
+  if (as == 0 || as == ULONG_MAX || *endptr != '\0')
+    {
+      vty_out (vty, "AS path value malformed%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ret = inet_aton (argv[1], &address);
+  if (ret == 0)
+    {
+      vty_out (vty, "Aggregator IP address is invalid%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  argstr = XMALLOC (MTYPE_ROUTE_MAP_COMPILED,
+		    strlen (argv[0]) + strlen (argv[1]) + 2);
+
+  sprintf (argstr, "%s %s", argv[0], argv[1]);
+
+  ret = bgp_route_set_delete (vty, vty->index, "aggregator as", argstr);
+
+  XFREE (MTYPE_ROUTE_MAP_COMPILED, argstr);
+
+  return ret;
+}
+
+ALIAS (no_set_aggregator_as,
+       no_set_aggregator_as_val_cmd,
+       "no set aggregator as <1-65535> A.B.C.D",
+       NO_STR
+       SET_STR
+       "BGP aggregator attribute\n"
+       "AS number of aggregator\n"
+       "AS number\n"
+       "IP address of aggregator\n")
+
+
+#ifdef HAVE_IPV6
+DEFUN (match_ipv6_address, 
+       match_ipv6_address_cmd,
+       "match ipv6 address WORD",
+       MATCH_STR
+       IPV6_STR
+       "Match IPv6 address of route\n"
+       "IPv6 access-list name\n")
+{
+  return bgp_route_match_add (vty, vty->index, "ipv6 address", argv[0]);
+}
+
+DEFUN (no_match_ipv6_address, 
+       no_match_ipv6_address_cmd,
+       "no match ipv6 address WORD",
+       NO_STR
+       MATCH_STR
+       IPV6_STR
+       "Match IPv6 address of route\n"
+       "IPv6 access-list name\n")
+{
+  return bgp_route_match_delete (vty, vty->index, "ipv6 address", argv[0]);
+}
+
+DEFUN (match_ipv6_next_hop, 
+       match_ipv6_next_hop_cmd,
+       "match ipv6 next-hop X:X::X:X",
+       MATCH_STR
+       IPV6_STR
+       "Match IPv6 next-hop address of route\n"
+       "IPv6 address of next hop\n")
+{
+  return bgp_route_match_add (vty, vty->index, "ipv6 next-hop", argv[0]);
+}
+
+DEFUN (no_match_ipv6_next_hop,
+       no_match_ipv6_next_hop_cmd,
+       "no match ipv6 next-hop X:X::X:X",
+       NO_STR
+       MATCH_STR
+       IPV6_STR
+       "Match IPv6 next-hop address of route\n"
+       "IPv6 address of next hop\n")
+{
+  return bgp_route_match_delete (vty, vty->index, "ipv6 next-hop", argv[0]);
+}
+
+DEFUN (match_ipv6_address_prefix_list, 
+       match_ipv6_address_prefix_list_cmd,
+       "match ipv6 address prefix-list WORD",
+       MATCH_STR
+       IPV6_STR
+       "Match address of route\n"
+       "Match entries of prefix-lists\n"
+       "IP prefix-list name\n")
+{
+  return bgp_route_match_add (vty, vty->index, "ipv6 address prefix-list", argv[0]);
+}
+
+DEFUN (no_match_ipv6_address_prefix_list,
+       no_match_ipv6_address_prefix_list_cmd,
+       "no match ipv6 address prefix-list WORD",
+       NO_STR
+       MATCH_STR
+       IPV6_STR
+       "Match address of route\n"
+       "Match entries of prefix-lists\n"
+       "IP prefix-list name\n")
+{
+  return bgp_route_match_delete (vty, vty->index, "ipv6 address prefix-list", argv[0]);
+}
+
+DEFUN (set_ipv6_nexthop_global,
+       set_ipv6_nexthop_global_cmd,
+       "set ipv6 next-hop global X:X::X:X",
+       SET_STR
+       IPV6_STR
+       "IPv6 next-hop address\n"
+       "IPv6 global address\n"
+       "IPv6 address of next hop\n")
+{
+  return bgp_route_set_add (vty, vty->index, "ipv6 next-hop global", argv[0]);
+}
+
+DEFUN (no_set_ipv6_nexthop_global,
+       no_set_ipv6_nexthop_global_cmd,
+       "no set ipv6 next-hop global",
+       NO_STR
+       SET_STR
+       IPV6_STR
+       "IPv6 next-hop address\n"
+       "IPv6 global address\n")
+{
+  if (argc == 0)
+    return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop global", NULL);
+
+  return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop global", argv[0]);
+}
+
+ALIAS (no_set_ipv6_nexthop_global,
+       no_set_ipv6_nexthop_global_val_cmd,
+       "no set ipv6 next-hop global X:X::X:X",
+       NO_STR
+       SET_STR
+       IPV6_STR
+       "IPv6 next-hop address\n"
+       "IPv6 global address\n"
+       "IPv6 address of next hop\n")
+
+DEFUN (set_ipv6_nexthop_local,
+       set_ipv6_nexthop_local_cmd,
+       "set ipv6 next-hop local X:X::X:X",
+       SET_STR
+       IPV6_STR
+       "IPv6 next-hop address\n"
+       "IPv6 local address\n"
+       "IPv6 address of next hop\n")
+{
+  return bgp_route_set_add (vty, vty->index, "ipv6 next-hop local", argv[0]);
+}
+
+DEFUN (no_set_ipv6_nexthop_local,
+       no_set_ipv6_nexthop_local_cmd,
+       "no set ipv6 next-hop local",
+       NO_STR
+       SET_STR
+       IPV6_STR
+       "IPv6 next-hop address\n"
+       "IPv6 local address\n")
+{
+  if (argc == 0)
+    return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop local", NULL);
+  
+  return bgp_route_set_delete (vty, vty->index, "ipv6 next-hop local", argv[0]);
+}
+
+ALIAS (no_set_ipv6_nexthop_local,
+       no_set_ipv6_nexthop_local_val_cmd,
+       "no set ipv6 next-hop local X:X::X:X",
+       NO_STR
+       SET_STR
+       IPV6_STR
+       "IPv6 next-hop address\n"
+       "IPv6 local address\n"
+       "IPv6 address of next hop\n")
+#endif /* HAVE_IPV6 */
+
+DEFUN (set_vpnv4_nexthop,
+       set_vpnv4_nexthop_cmd,
+       "set vpnv4 next-hop A.B.C.D",
+       SET_STR
+       "VPNv4 information\n"
+       "VPNv4 next-hop address\n"
+       "IP address of next hop\n")
+{
+  return bgp_route_set_add (vty, vty->index, "vpnv4 next-hop", argv[0]);
+}
+
+DEFUN (no_set_vpnv4_nexthop,
+       no_set_vpnv4_nexthop_cmd,
+       "no set vpnv4 next-hop",
+       NO_STR
+       SET_STR
+       "VPNv4 information\n"
+       "VPNv4 next-hop address\n")
+{
+  if (argc == 0)
+    return bgp_route_set_delete (vty, vty->index, "vpnv4 next-hop", NULL);
+
+  return bgp_route_set_delete (vty, vty->index, "vpnv4 next-hop", argv[0]);
+}
+
+ALIAS (no_set_vpnv4_nexthop,
+       no_set_vpnv4_nexthop_val_cmd,
+       "no set vpnv4 next-hop A.B.C.D",
+       NO_STR
+       SET_STR
+       "VPNv4 information\n"
+       "VPNv4 next-hop address\n"
+       "IP address of next hop\n")
+
+DEFUN (set_originator_id,
+       set_originator_id_cmd,
+       "set originator-id A.B.C.D",
+       SET_STR
+       "BGP originator ID attribute\n"
+       "IP address of originator\n")
+{
+  return bgp_route_set_add (vty, vty->index, "originator-id", argv[0]);
+}
+
+DEFUN (no_set_originator_id,
+       no_set_originator_id_cmd,
+       "no set originator-id",
+       NO_STR
+       SET_STR
+       "BGP originator ID attribute\n")
+{
+  if (argc == 0)
+    return bgp_route_set_delete (vty, vty->index, "originator-id", NULL);
+  
+  return bgp_route_set_delete (vty, vty->index, "originator-id", argv[0]);
+}
+
+ALIAS (no_set_originator_id,
+       no_set_originator_id_val_cmd,
+       "no set originator-id A.B.C.D",
+       NO_STR
+       SET_STR
+       "BGP originator ID attribute\n"
+       "IP address of originator\n")
+
+
+/* Initialization of route map. */
+void
+bgp_route_map_init ()
+{
+  route_map_init ();
+  route_map_init_vty ();
+  route_map_add_hook (bgp_route_map_update);
+  route_map_delete_hook (bgp_route_map_update);
+
+  route_map_install_match (&route_match_ip_address_cmd);
+  route_map_install_match (&route_match_ip_next_hop_cmd);
+  route_map_install_match (&route_match_ip_address_prefix_list_cmd);
+  route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd);
+  route_map_install_match (&route_match_aspath_cmd);
+  route_map_install_match (&route_match_community_cmd);
+  route_map_install_match (&route_match_metric_cmd);
+  route_map_install_match (&route_match_origin_cmd);
+
+  route_map_install_set (&route_set_ip_nexthop_cmd);
+  route_map_install_set (&route_set_local_pref_cmd);
+  route_map_install_set (&route_set_weight_cmd);
+  route_map_install_set (&route_set_metric_cmd);
+  route_map_install_set (&route_set_aspath_prepend_cmd);
+  route_map_install_set (&route_set_origin_cmd);
+  route_map_install_set (&route_set_atomic_aggregate_cmd);
+  route_map_install_set (&route_set_aggregator_as_cmd);
+  route_map_install_set (&route_set_community_cmd);
+  route_map_install_set (&route_set_community_delete_cmd);
+  route_map_install_set (&route_set_vpnv4_nexthop_cmd);
+  route_map_install_set (&route_set_originator_id_cmd);
+  route_map_install_set (&route_set_ecommunity_rt_cmd);
+  route_map_install_set (&route_set_ecommunity_soo_cmd);
+
+  install_element (RMAP_NODE, &match_ip_address_cmd);
+  install_element (RMAP_NODE, &no_match_ip_address_cmd);
+  install_element (RMAP_NODE, &no_match_ip_address_val_cmd);
+  install_element (RMAP_NODE, &match_ip_next_hop_cmd);
+  install_element (RMAP_NODE, &no_match_ip_next_hop_cmd);
+  install_element (RMAP_NODE, &no_match_ip_next_hop_val_cmd);
+
+  install_element (RMAP_NODE, &match_ip_address_prefix_list_cmd);
+  install_element (RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
+  install_element (RMAP_NODE, &no_match_ip_address_prefix_list_val_cmd);
+  install_element (RMAP_NODE, &match_ip_next_hop_prefix_list_cmd);
+  install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
+  install_element (RMAP_NODE, &no_match_ip_next_hop_prefix_list_val_cmd);
+
+  install_element (RMAP_NODE, &match_aspath_cmd);
+  install_element (RMAP_NODE, &no_match_aspath_cmd);
+  install_element (RMAP_NODE, &no_match_aspath_val_cmd);
+  install_element (RMAP_NODE, &match_metric_cmd);
+  install_element (RMAP_NODE, &no_match_metric_cmd);
+  install_element (RMAP_NODE, &no_match_metric_val_cmd);
+  install_element (RMAP_NODE, &match_community_cmd);
+  install_element (RMAP_NODE, &match_community_exact_cmd);
+  install_element (RMAP_NODE, &no_match_community_cmd);
+  install_element (RMAP_NODE, &no_match_community_val_cmd);
+  install_element (RMAP_NODE, &no_match_community_exact_cmd);
+  install_element (RMAP_NODE, &match_origin_cmd);
+  install_element (RMAP_NODE, &no_match_origin_cmd);
+  install_element (RMAP_NODE, &no_match_origin_val_cmd);
+
+  install_element (RMAP_NODE, &set_ip_nexthop_cmd);
+  install_element (RMAP_NODE, &no_set_ip_nexthop_cmd);
+  install_element (RMAP_NODE, &no_set_ip_nexthop_val_cmd);
+  install_element (RMAP_NODE, &set_local_pref_cmd);
+  install_element (RMAP_NODE, &no_set_local_pref_cmd);
+  install_element (RMAP_NODE, &no_set_local_pref_val_cmd);
+  install_element (RMAP_NODE, &set_weight_cmd);
+  install_element (RMAP_NODE, &no_set_weight_cmd);
+  install_element (RMAP_NODE, &no_set_weight_val_cmd);
+  install_element (RMAP_NODE, &set_metric_cmd);
+  install_element (RMAP_NODE, &no_set_metric_cmd);
+  install_element (RMAP_NODE, &no_set_metric_val_cmd);
+  install_element (RMAP_NODE, &set_aspath_prepend_cmd);
+  install_element (RMAP_NODE, &no_set_aspath_prepend_cmd);
+  install_element (RMAP_NODE, &no_set_aspath_prepend_val_cmd);
+  install_element (RMAP_NODE, &set_origin_cmd);
+  install_element (RMAP_NODE, &no_set_origin_cmd);
+  install_element (RMAP_NODE, &no_set_origin_val_cmd);
+  install_element (RMAP_NODE, &set_atomic_aggregate_cmd);
+  install_element (RMAP_NODE, &no_set_atomic_aggregate_cmd);
+  install_element (RMAP_NODE, &set_aggregator_as_cmd);
+  install_element (RMAP_NODE, &no_set_aggregator_as_cmd);
+  install_element (RMAP_NODE, &no_set_aggregator_as_val_cmd);
+  install_element (RMAP_NODE, &set_community_cmd);
+  install_element (RMAP_NODE, &set_community_none_cmd);
+  install_element (RMAP_NODE, &no_set_community_cmd);
+  install_element (RMAP_NODE, &no_set_community_val_cmd);
+  install_element (RMAP_NODE, &no_set_community_none_cmd);
+  install_element (RMAP_NODE, &set_community_delete_cmd);
+  install_element (RMAP_NODE, &no_set_community_delete_cmd);
+  install_element (RMAP_NODE, &no_set_community_delete_val_cmd);
+  install_element (RMAP_NODE, &set_ecommunity_rt_cmd);
+  install_element (RMAP_NODE, &no_set_ecommunity_rt_cmd);
+  install_element (RMAP_NODE, &no_set_ecommunity_rt_val_cmd);
+  install_element (RMAP_NODE, &set_ecommunity_soo_cmd);
+  install_element (RMAP_NODE, &no_set_ecommunity_soo_cmd);
+  install_element (RMAP_NODE, &no_set_ecommunity_soo_val_cmd);
+  install_element (RMAP_NODE, &set_vpnv4_nexthop_cmd);
+  install_element (RMAP_NODE, &no_set_vpnv4_nexthop_cmd);
+  install_element (RMAP_NODE, &no_set_vpnv4_nexthop_val_cmd);
+  install_element (RMAP_NODE, &set_originator_id_cmd);
+  install_element (RMAP_NODE, &no_set_originator_id_cmd);
+  install_element (RMAP_NODE, &no_set_originator_id_val_cmd);
+
+#ifdef HAVE_IPV6
+  route_map_install_match (&route_match_ipv6_address_cmd);
+  route_map_install_match (&route_match_ipv6_next_hop_cmd);
+  route_map_install_match (&route_match_ipv6_address_prefix_list_cmd);
+  route_map_install_set (&route_set_ipv6_nexthop_global_cmd);
+  route_map_install_set (&route_set_ipv6_nexthop_local_cmd);
+
+  install_element (RMAP_NODE, &match_ipv6_address_cmd);
+  install_element (RMAP_NODE, &no_match_ipv6_address_cmd);
+  install_element (RMAP_NODE, &match_ipv6_next_hop_cmd);
+  install_element (RMAP_NODE, &no_match_ipv6_next_hop_cmd);
+  install_element (RMAP_NODE, &match_ipv6_address_prefix_list_cmd);
+  install_element (RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd);
+  install_element (RMAP_NODE, &set_ipv6_nexthop_global_cmd);
+  install_element (RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
+  install_element (RMAP_NODE, &no_set_ipv6_nexthop_global_val_cmd);
+  install_element (RMAP_NODE, &set_ipv6_nexthop_local_cmd);
+  install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_cmd);
+  install_element (RMAP_NODE, &no_set_ipv6_nexthop_local_val_cmd);
+#endif /* HAVE_IPV6 */
+}
diff --git a/bgpd/bgp_snmp.c b/bgpd/bgp_snmp.c
new file mode 100644
index 0000000..bf9c7f8
--- /dev/null
+++ b/bgpd/bgp_snmp.c
@@ -0,0 +1,875 @@
+/* BGP4 SNMP support
+   Copyright (C) 1999, 2000 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#ifdef HAVE_SNMP
+#include <asn1.h>
+#include <snmp.h>
+#include <snmp_impl.h>
+
+#include "if.h"
+#include "log.h"
+#include "prefix.h"
+#include "command.h"
+#include "thread.h"
+#include "smux.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_table.h"
+#include "bgpd/bgp_aspath.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_fsm.h"
+
+/* BGP4-MIB described in RFC1657. */
+#define BGP4MIB 1,3,6,1,2,1,15
+
+/* Zebra enterprise BGP MIB.  This variable is used for register
+   OSPF MIB to SNMP agent under SMUX protocol.  */
+#define BGPDMIB 1,3,6,1,4,1,3317,1,2,2
+
+/* BGP MIB bgpVersion. */
+#define BGPVERSION			      0
+
+/* BGP MIB bgpLocalAs. */
+#define BGPLOCALAS			      0
+
+/* BGP MIB bgpPeerTable. */
+#define BGPPEERIDENTIFIER                     1
+#define BGPPEERSTATE                          2
+#define BGPPEERADMINSTATUS                    3
+#define BGPPEERNEGOTIATEDVERSION              4
+#define BGPPEERLOCALADDR                      5
+#define BGPPEERLOCALPORT                      6
+#define BGPPEERREMOTEADDR                     7
+#define BGPPEERREMOTEPORT                     8
+#define BGPPEERREMOTEAS                       9
+#define BGPPEERINUPDATES                     10
+#define BGPPEEROUTUPDATES                    11
+#define BGPPEERINTOTALMESSAGES               12
+#define BGPPEEROUTTOTALMESSAGES              13
+#define BGPPEERLASTERROR                     14
+#define BGPPEERFSMESTABLISHEDTRANSITIONS     15
+#define BGPPEERFSMESTABLISHEDTIME            16
+#define BGPPEERCONNECTRETRYINTERVAL          17
+#define BGPPEERHOLDTIME                      18
+#define BGPPEERKEEPALIVE                     19
+#define BGPPEERHOLDTIMECONFIGURED            20
+#define BGPPEERKEEPALIVECONFIGURED           21
+#define BGPPEERMINASORIGINATIONINTERVAL      22
+#define BGPPEERMINROUTEADVERTISEMENTINTERVAL 23
+#define BGPPEERINUPDATEELAPSEDTIME           24
+
+/* BGP MIB bgpIdentifier. */
+#define BGPIDENTIFIER                         0
+
+/* BGP MIB bgpRcvdPathAttrTable */
+#define BGPPATHATTRPEER                       1
+#define BGPPATHATTRDESTNETWORK                2
+#define BGPPATHATTRORIGIN                     3
+#define BGPPATHATTRASPATH                     4
+#define BGPPATHATTRNEXTHOP                    5
+#define BGPPATHATTRINTERASMETRIC              6
+
+/* BGP MIB bgp4PathAttrTable. */
+#define BGP4PATHATTRPEER                      1
+#define BGP4PATHATTRIPADDRPREFIXLEN           2
+#define BGP4PATHATTRIPADDRPREFIX              3
+#define BGP4PATHATTRORIGIN                    4
+#define BGP4PATHATTRASPATHSEGMENT             5
+#define BGP4PATHATTRNEXTHOP                   6
+#define BGP4PATHATTRMULTIEXITDISC             7
+#define BGP4PATHATTRLOCALPREF                 8
+#define BGP4PATHATTRATOMICAGGREGATE           9
+#define BGP4PATHATTRAGGREGATORAS             10
+#define BGP4PATHATTRAGGREGATORADDR           11
+#define BGP4PATHATTRCALCLOCALPREF            12
+#define BGP4PATHATTRBEST                     13
+#define BGP4PATHATTRUNKNOWN                  14
+
+/* SNMP value hack. */
+#define INTEGER ASN_INTEGER
+#define INTEGER32 ASN_INTEGER
+#define COUNTER32 ASN_COUNTER
+#define OCTET_STRING ASN_OCTET_STR
+#define IPADDRESS ASN_IPADDRESS
+#define GAUGE32 ASN_UNSIGNED
+
+/* Declare static local variables for convenience. */
+SNMP_LOCAL_VARIABLES
+
+/* BGP-MIB instances. */
+oid bgp_oid [] = { BGP4MIB };
+oid bgpd_oid [] = { BGPDMIB };
+
+/* IP address 0.0.0.0. */
+static struct in_addr bgp_empty_addr = {0};
+
+/* Hook functions. */
+static u_char *bgpVersion ();
+static u_char *bgpLocalAs ();
+static u_char *bgpPeerTable ();
+static u_char *bgpRcvdPathAttrTable ();
+static u_char *bgpIdentifier ();
+static u_char *bgp4PathAttrTable ();
+/* static u_char *bgpTraps (); */
+
+struct variable bgp_variables[] = 
+{
+  /* BGP version. */
+  {BGPVERSION,                OCTET_STRING, RONLY, bgpVersion,
+   1, {1}},
+  /* BGP local AS. */
+  {BGPLOCALAS,                INTEGER, RONLY, bgpLocalAs,
+   1, {2}},
+  /* BGP peer table. */
+  {BGPPEERIDENTIFIER,         IPADDRESS, RONLY, bgpPeerTable,
+   3, {3, 1, 1}},
+  {BGPPEERSTATE,              INTEGER, RONLY, bgpPeerTable,
+   3, {3, 1, 2}},
+  {BGPPEERADMINSTATUS,        INTEGER, RWRITE, bgpPeerTable,
+   3, {3, 1, 3}},
+  {BGPPEERNEGOTIATEDVERSION,  INTEGER32, RONLY, bgpPeerTable,
+   3, {3, 1, 4}},
+  {BGPPEERLOCALADDR,          IPADDRESS, RONLY, bgpPeerTable,
+   3, {3, 1, 5}},
+  {BGPPEERLOCALPORT,          INTEGER, RONLY, bgpPeerTable,
+   3, {3, 1, 6}},
+  {BGPPEERREMOTEADDR,         IPADDRESS, RONLY, bgpPeerTable,
+   3, {3, 1, 7}},
+  {BGPPEERREMOTEPORT,         INTEGER, RONLY, bgpPeerTable,
+   3, {3, 1, 8}},
+  {BGPPEERREMOTEAS,           INTEGER, RONLY, bgpPeerTable,
+   3, {3, 1, 9}},
+  {BGPPEERINUPDATES,          COUNTER32, RONLY, bgpPeerTable,
+   3, {3, 1, 10}},
+  {BGPPEEROUTUPDATES,         COUNTER32, RONLY, bgpPeerTable,
+   3, {3, 1, 11}},
+  {BGPPEERINTOTALMESSAGES,    COUNTER32, RONLY, bgpPeerTable,
+   3, {3, 1, 12}},
+  {BGPPEEROUTTOTALMESSAGES,   COUNTER32, RONLY, bgpPeerTable,
+   3, {3, 1, 13}},
+  {BGPPEERLASTERROR,          OCTET_STRING, RONLY, bgpPeerTable,
+   3, {3, 1, 14}},
+  {BGPPEERFSMESTABLISHEDTRANSITIONS, COUNTER32, RONLY, bgpPeerTable,
+   3, {3, 1, 15}},
+  {BGPPEERFSMESTABLISHEDTIME, GAUGE32, RONLY, bgpPeerTable,
+   3, {3, 1, 16}},
+  {BGPPEERCONNECTRETRYINTERVAL, INTEGER, RWRITE, bgpPeerTable,
+   3, {3, 1, 17}},
+  {BGPPEERHOLDTIME,           INTEGER, RONLY, bgpPeerTable,
+   3, {3, 1, 18}},
+  {BGPPEERKEEPALIVE,          INTEGER, RONLY, bgpPeerTable,
+   3, {3, 1, 19}},
+  {BGPPEERHOLDTIMECONFIGURED, INTEGER, RWRITE, bgpPeerTable,
+   3, {3, 1, 20}},
+  {BGPPEERKEEPALIVECONFIGURED, INTEGER, RWRITE, bgpPeerTable,
+   3, {3, 1, 21}},
+  {BGPPEERMINASORIGINATIONINTERVAL, INTEGER, RWRITE, bgpPeerTable,
+   3, {3, 1, 22}},
+  {BGPPEERMINROUTEADVERTISEMENTINTERVAL, INTEGER, RWRITE, bgpPeerTable,
+   3, {3, 1, 23}},
+  {BGPPEERINUPDATEELAPSEDTIME, GAUGE32, RONLY, bgpPeerTable,
+   3, {3, 1, 24}},
+  /* BGP identifier. */
+  {BGPIDENTIFIER,             IPADDRESS, RONLY, bgpIdentifier,
+   1, {4}},
+  /* BGP received path attribute table. */
+  {BGPPATHATTRPEER,           IPADDRESS, RONLY, bgpRcvdPathAttrTable,
+   3, {5, 1, 1}},
+  {BGPPATHATTRDESTNETWORK,    IPADDRESS, RONLY, bgpRcvdPathAttrTable,
+   3, {5, 1, 2}},
+  {BGPPATHATTRORIGIN,         INTEGER, RONLY, bgpRcvdPathAttrTable,
+   3, {5, 1, 3}},
+  {BGPPATHATTRASPATH,         OCTET_STRING, RONLY, bgpRcvdPathAttrTable,
+   3, {5, 1, 4}},
+  {BGPPATHATTRNEXTHOP,        IPADDRESS, RONLY, bgpRcvdPathAttrTable,
+   3, {5, 1, 5}},
+  {BGPPATHATTRINTERASMETRIC,  INTEGER32, RONLY, bgpRcvdPathAttrTable,
+   3, {5, 1, 6}},
+  /* BGP-4 received path attribute table. */
+  {BGP4PATHATTRPEER, IPADDRESS, RONLY, bgp4PathAttrTable,
+   3, {6, 1, 1}},
+  {BGP4PATHATTRIPADDRPREFIXLEN, INTEGER, RONLY, bgp4PathAttrTable,
+   3, {6, 1, 2}},
+  {BGP4PATHATTRIPADDRPREFIX,  IPADDRESS, RONLY, bgp4PathAttrTable,
+   3, {6, 1, 3}},
+  {BGP4PATHATTRORIGIN,        INTEGER, RONLY, bgp4PathAttrTable,
+   3, {6, 1, 4}},
+  {BGP4PATHATTRASPATHSEGMENT, OCTET_STRING, RONLY, bgp4PathAttrTable,
+   3, {6, 1, 5}},
+  {BGP4PATHATTRNEXTHOP,       IPADDRESS, RONLY, bgp4PathAttrTable,
+   3, {6, 1, 6}},
+  {BGP4PATHATTRMULTIEXITDISC, INTEGER, RONLY, bgp4PathAttrTable,
+   3, {6, 1, 7}},
+  {BGP4PATHATTRLOCALPREF,     INTEGER, RONLY, bgp4PathAttrTable,
+   3, {6, 1, 8}},
+  {BGP4PATHATTRATOMICAGGREGATE, INTEGER, RONLY, bgp4PathAttrTable,
+   3, {6, 1, 9}},
+  {BGP4PATHATTRAGGREGATORAS,  INTEGER, RONLY, bgp4PathAttrTable,
+   3, {6, 1, 10}},
+  {BGP4PATHATTRAGGREGATORADDR, IPADDRESS, RONLY, bgp4PathAttrTable,
+   3, {6, 1, 11}},
+  {BGP4PATHATTRCALCLOCALPREF, INTEGER, RONLY, bgp4PathAttrTable,
+   3, {6, 1, 12}},
+  {BGP4PATHATTRBEST,          INTEGER, RONLY, bgp4PathAttrTable,
+   3, {6, 1, 13}},
+  {BGP4PATHATTRUNKNOWN,       OCTET_STRING, RONLY, bgp4PathAttrTable,
+   3, {6, 1, 14}},
+};
+
+static u_char *
+bgpVersion (struct variable *v, oid name[], size_t *length, int exact,
+	    size_t *var_len, WriteMethod **write_method)
+{
+  static u_char version;
+
+  if (smux_header_generic(v, name, length, exact, var_len, write_method)
+      == MATCH_FAILED)
+    return NULL;
+
+  /* Retrun BGP version.  Zebra bgpd only support version 4. */
+  version = (0x80 >> (BGP_VERSION_4 - 1));
+
+  /* Return octet string length 1. */
+  *var_len = 1;
+  return (u_char *)&version;
+}
+
+static u_char *
+bgpLocalAs (struct variable *v, oid name[], size_t *length,
+	    int exact, size_t *var_len, WriteMethod **write_method)
+{
+  struct bgp *bgp;
+
+  if (smux_header_generic(v, name, length, exact, var_len, write_method)
+      == MATCH_FAILED)
+    return NULL;
+
+  /* Get BGP structure. */
+  bgp = bgp_get_default ();
+  if (! bgp)
+    return NULL;
+
+  return SNMP_INTEGER (bgp->as);
+}
+
+struct peer *
+peer_lookup_addr_ipv4 (struct in_addr *src)
+{
+  struct bgp *bgp;
+  struct peer *peer;
+  struct listnode *nn;
+  struct in_addr addr;
+  int ret;
+
+  bgp = bgp_get_default ();
+  if (! bgp)
+    return NULL;
+
+  LIST_LOOP (bgp->peer, peer, nn)
+    {
+      ret = inet_pton (AF_INET, peer->host, &addr);
+      if (ret > 0)
+	{
+	  if (IPV4_ADDR_SAME (&addr, src))
+	    return peer;
+	}
+    }
+  return NULL;
+}
+
+struct peer *
+bgp_peer_lookup_next (struct in_addr *src)
+{
+  struct bgp *bgp;
+  struct peer *peer;
+  struct listnode *nn;
+  struct in_addr *p;
+  union sockunion su;
+  int ret;
+
+  memset (&su, 0, sizeof (union sockunion));
+
+  bgp = bgp_get_default ();
+  if (! bgp)
+    return NULL;
+
+  LIST_LOOP (bgp->peer, peer, nn)
+    {
+      ret = inet_pton (AF_INET, peer->host, &su.sin.sin_addr);
+      if (ret > 0)
+	{
+	  p = &su.sin.sin_addr;
+
+	  if (ntohl (p->s_addr) > ntohl (src->s_addr))
+	    {
+	      src->s_addr = p->s_addr;
+	      return peer;
+	    }
+	}
+    }
+  return NULL;
+}
+
+struct peer *
+bgpPeerTable_lookup (struct variable *v, oid name[], size_t *length, 
+		     struct in_addr *addr, int exact)
+{
+  struct peer *peer = NULL;
+  int len;
+
+  if (exact)
+    {
+      /* Check the length. */
+      if (*length - v->namelen != sizeof (struct in_addr))
+	return NULL;
+
+      oid2in_addr (name + v->namelen, IN_ADDR_SIZE, addr);
+
+      peer = peer_lookup_addr_ipv4 (addr);
+      return peer;
+    }
+  else
+    {
+      len = *length - v->namelen;
+      if (len > 4) len = 4;
+      
+      oid2in_addr (name + v->namelen, len, addr);
+      
+      peer = bgp_peer_lookup_next (addr);
+
+      if (peer == NULL)
+	return NULL;
+
+      oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr));
+      *length = sizeof (struct in_addr) + v->namelen;
+
+      return peer;
+    }
+  return NULL;
+}
+
+/* BGP write methods. */
+int
+write_bgpPeerTable (int action, u_char *var_val,
+		    u_char var_val_type, size_t var_val_len,
+		    u_char *statP, oid *name, size_t length,
+		    struct variable *v)
+{
+  struct in_addr addr;
+  struct peer *peer;
+  long intval;
+  int bigsize = SNMP_MAX_LEN;
+  
+  if (var_val_type != ASN_INTEGER) 
+    {
+      return SNMP_ERR_WRONGTYPE;
+    }
+  if (var_val_len != sizeof (long)) 
+    {
+      return SNMP_ERR_WRONGLENGTH;
+    }
+
+  if (! asn_parse_int(var_val, &bigsize, &var_val_type,
+                      &intval, sizeof(long)))
+    {
+      return SNMP_ERR_WRONGENCODING;
+    }
+
+  memset (&addr, 0, sizeof (struct in_addr));
+
+  peer = bgpPeerTable_lookup (v, name, &length, &addr, 1);
+  if (! peer)
+    return SNMP_ERR_NOSUCHNAME;
+
+  printf ("val: %ld\n", intval);
+
+  switch (v->magic)
+    {
+    case BGPPEERADMINSTATUS:
+#define BGP_PeerAdmin_stop  1
+#define BGP_PeerAdmin_start 2
+      /* When the peer is established,   */
+      if (intval == BGP_PeerAdmin_stop)
+	BGP_EVENT_ADD (peer, BGP_Stop);
+      else if (intval == BGP_PeerAdmin_start)
+	;			/* Do nothing. */
+      else
+	return SNMP_ERR_NOSUCHNAME;
+      break;
+    case BGPPEERCONNECTRETRYINTERVAL:
+      SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
+      peer->connect = intval;
+      peer->v_connect = intval;
+      break;
+    case BGPPEERHOLDTIMECONFIGURED:
+      SET_FLAG (peer->config, PEER_CONFIG_TIMER);
+      peer->holdtime = intval;
+      peer->v_holdtime = intval;
+      break;
+    case BGPPEERKEEPALIVECONFIGURED:
+      SET_FLAG (peer->config, PEER_CONFIG_TIMER);
+      peer->keepalive = intval;
+      peer->v_keepalive = intval;
+      break;
+    case BGPPEERMINASORIGINATIONINTERVAL:
+      peer->v_asorig = intval;
+      break;
+    case BGPPEERMINROUTEADVERTISEMENTINTERVAL:
+      peer->v_routeadv = intval;
+      break;
+    }
+  return SNMP_ERR_NOERROR;
+}
+
+u_char *
+bgpPeerTable (struct variable *v, oid name[], size_t *length,
+	      int exact, size_t *var_len, WriteMethod **write_method)
+{
+  static struct in_addr addr;
+  struct peer *peer;
+
+  *write_method = NULL;
+  memset (&addr, 0, sizeof (struct in_addr));
+
+  peer = bgpPeerTable_lookup (v, name, length, &addr, exact);
+  if (! peer)
+    return NULL;
+
+  switch (v->magic)
+    {
+    case BGPPEERIDENTIFIER:
+      return SNMP_IPADDRESS (peer->remote_id);
+      break;
+    case BGPPEERSTATE:
+      return SNMP_INTEGER (peer->status);
+      break;
+    case BGPPEERADMINSTATUS:
+      *write_method = write_bgpPeerTable;
+#define BGP_PeerAdmin_stop  1
+#define BGP_PeerAdmin_start 2
+      if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
+	return SNMP_INTEGER (BGP_PeerAdmin_stop);
+      else
+	return SNMP_INTEGER (BGP_PeerAdmin_start);
+      break;
+    case BGPPEERNEGOTIATEDVERSION:
+      return SNMP_INTEGER (peer->version);
+      break;
+    case BGPPEERLOCALADDR:
+      if (peer->su_local)
+	return SNMP_IPADDRESS (peer->su_local->sin.sin_addr);
+      else
+	return SNMP_IPADDRESS (bgp_empty_addr);
+      break;
+    case BGPPEERLOCALPORT:
+      if (peer->su_local)
+	return SNMP_INTEGER (ntohs (peer->su_local->sin.sin_port));
+      else
+	return SNMP_INTEGER (0);
+      break;
+    case BGPPEERREMOTEADDR:
+      if (peer->su_remote)
+	return SNMP_IPADDRESS (peer->su_remote->sin.sin_addr);
+      else
+	return SNMP_IPADDRESS (bgp_empty_addr);
+      break;
+    case BGPPEERREMOTEPORT:
+      if (peer->su_remote)
+	return SNMP_INTEGER (ntohs (peer->su_remote->sin.sin_port));
+      else
+	return SNMP_INTEGER (0);
+      break;
+    case BGPPEERREMOTEAS:
+      return SNMP_INTEGER (peer->as);
+      break;
+    case BGPPEERINUPDATES:
+      return SNMP_INTEGER (peer->update_in);
+      break;
+    case BGPPEEROUTUPDATES:
+      return SNMP_INTEGER (peer->update_out);
+      break;
+    case BGPPEERINTOTALMESSAGES:
+      return SNMP_INTEGER (peer->open_in + peer->update_in
+			   + peer->keepalive_in + peer->notify_in
+			   + peer->refresh_in + peer->dynamic_cap_in);
+      break;
+    case BGPPEEROUTTOTALMESSAGES:
+      return SNMP_INTEGER (peer->open_out + peer->update_out
+			   + peer->keepalive_out + peer->notify_out
+			   + peer->refresh_out, peer->dynamic_cap_out);
+      break;
+    case BGPPEERLASTERROR:
+      {
+	static u_char lasterror[2];
+	lasterror[0] = peer->notify.code;
+	lasterror[1] = peer->notify.subcode;
+	*var_len = 2;
+	return (u_char *)&lasterror;
+      }
+      break;
+    case BGPPEERFSMESTABLISHEDTRANSITIONS:
+      return SNMP_INTEGER (peer->established);
+      break;
+    case BGPPEERFSMESTABLISHEDTIME:
+      if (peer->uptime == 0)
+	return SNMP_INTEGER (0);
+      else
+	return SNMP_INTEGER (time (NULL) - peer->uptime);
+      break;
+    case BGPPEERCONNECTRETRYINTERVAL:
+      *write_method = write_bgpPeerTable;
+      return SNMP_INTEGER (peer->v_connect);
+      break;
+    case BGPPEERHOLDTIME:
+      return SNMP_INTEGER (peer->v_holdtime);
+      break;
+    case BGPPEERKEEPALIVE:
+      return SNMP_INTEGER (peer->v_keepalive);
+      break;
+    case BGPPEERHOLDTIMECONFIGURED:
+      *write_method = write_bgpPeerTable;
+      if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
+	return SNMP_INTEGER (peer->holdtime);
+      else
+	return SNMP_INTEGER (peer->v_holdtime);
+      break;
+    case BGPPEERKEEPALIVECONFIGURED:
+      *write_method = write_bgpPeerTable;
+      if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
+	return SNMP_INTEGER (peer->keepalive);
+      else
+	return SNMP_INTEGER (peer->v_keepalive);
+      break;
+    case BGPPEERMINASORIGINATIONINTERVAL:
+      *write_method = write_bgpPeerTable;
+      return SNMP_INTEGER (peer->v_asorig);
+      break;
+    case BGPPEERMINROUTEADVERTISEMENTINTERVAL:
+      *write_method = write_bgpPeerTable;
+      return SNMP_INTEGER (peer->v_routeadv);
+      break;
+    case BGPPEERINUPDATEELAPSEDTIME:
+      if (peer->update_time == 0)
+	return SNMP_INTEGER (0);
+      else
+	return SNMP_INTEGER (time (NULL) - peer->update_time);
+      break;
+    default:
+      return NULL;
+      break;
+    }  
+  return NULL;
+}
+
+u_char *
+bgpIdentifier (struct variable *v, oid name[], size_t *length,
+	       int exact, size_t *var_len, WriteMethod **write_method)
+{
+  struct bgp *bgp;
+
+  if (smux_header_generic(v, name, length, exact, var_len, write_method)
+      == MATCH_FAILED)
+    return NULL;
+
+  bgp = bgp_get_default ();
+  if (!bgp)
+    return NULL;
+
+  return SNMP_IPADDRESS (bgp->router_id);
+}
+
+u_char *
+bgpRcvdPathAttrTable (struct variable *v, oid name[], size_t *length,
+		      int exact, size_t *var_len, WriteMethod **write_method)
+{
+  /* Received Path Attribute Table.  This table contains, one entry
+     per path to a network, path attributes received from all peers
+     running BGP version 3 or less.  This table is obsolete, having
+     been replaced in functionality with the bgp4PathAttrTable.  */
+  return NULL;
+}
+
+struct bgp_info *
+bgp4PathAttrLookup (struct variable *v, oid name[], size_t *length,
+		    struct bgp *bgp, struct prefix_ipv4 *addr, int exact)
+{
+  oid *offset;
+  int offsetlen;
+  struct bgp_info *binfo;
+  struct bgp_info *min;
+  struct bgp_node *rn;
+  union sockunion su;
+  int len;
+  struct in_addr paddr;
+
+#define BGP_PATHATTR_ENTRY_OFFSET \
+          (IN_ADDR_SIZE + 1 + IN_ADDR_SIZE)
+
+  if (exact)
+    {
+      if (*length - v->namelen != BGP_PATHATTR_ENTRY_OFFSET)
+	return NULL;
+
+      /* Set OID offset for prefix. */
+      offset = name + v->namelen;
+      oid2in_addr (offset, IN_ADDR_SIZE, &addr->prefix);
+      offset += IN_ADDR_SIZE;
+
+      /* Prefix length. */
+      addr->prefixlen = *offset;
+      offset++;
+
+      /* Peer address. */
+      su.sin.sin_family = AF_INET;
+      oid2in_addr (offset, IN_ADDR_SIZE, &su.sin.sin_addr);
+
+      /* Lookup node. */
+      rn = bgp_node_lookup (bgp->rib[AFI_IP][SAFI_UNICAST], 
+			      (struct prefix *) addr);
+      if (rn)
+	{
+	  bgp_unlock_node (rn);
+
+	  for (binfo = rn->info; binfo; binfo = binfo->next)
+	    if (sockunion_same (&binfo->peer->su, &su))
+	      return binfo;
+	}
+    }
+  else
+    {
+      offset = name + v->namelen;
+      offsetlen = *length - v->namelen;
+      len = offsetlen;
+
+      if (offsetlen == 0)
+	rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_UNICAST]);
+      else
+	{
+	  if (len > IN_ADDR_SIZE)
+	    len = IN_ADDR_SIZE;
+      
+	  oid2in_addr (offset, len, &addr->prefix);
+
+	  offset += IN_ADDR_SIZE;
+	  offsetlen -= IN_ADDR_SIZE;
+
+	  if (offsetlen > 0)
+	    addr->prefixlen = *offset;
+	  else
+	    addr->prefixlen = len * 8;
+
+	  rn = bgp_node_get (bgp->rib[AFI_IP][SAFI_UNICAST],
+			       (struct prefix *) addr);
+
+	  offset++;
+	  offsetlen--;
+	}
+
+      if (offsetlen > 0)
+	{
+	  len = offsetlen;
+	  if (len > IN_ADDR_SIZE)
+	    len = IN_ADDR_SIZE;
+
+	  oid2in_addr (offset, len, &paddr);
+	}
+      else
+	paddr.s_addr = 0;
+
+      if (! rn)
+	return NULL;
+
+      do
+	{
+	  min = NULL;
+
+	  for (binfo = rn->info; binfo; binfo = binfo->next)
+	    {
+	      if (binfo->peer->su.sin.sin_family == AF_INET
+		  && ntohl (paddr.s_addr) 
+		  < ntohl (binfo->peer->su.sin.sin_addr.s_addr))
+		{
+		  if (min)
+		    {
+		      if (ntohl (binfo->peer->su.sin.sin_addr.s_addr) 
+			  < ntohl (min->peer->su.sin.sin_addr.s_addr))
+			min = binfo;
+		    }
+		  else
+		    min = binfo;
+		}
+	    }
+
+	  if (min)
+	    {
+	      *length = v->namelen + BGP_PATHATTR_ENTRY_OFFSET;
+
+	      offset = name + v->namelen;
+	      oid_copy_addr (offset, &rn->p.u.prefix4, IN_ADDR_SIZE);
+	      offset += IN_ADDR_SIZE;
+	      *offset = rn->p.prefixlen;
+	      offset++;
+	      oid_copy_addr (offset, &min->peer->su.sin.sin_addr, 
+			     IN_ADDR_SIZE);
+	      addr->prefix = rn->p.u.prefix4;
+	      addr->prefixlen = rn->p.prefixlen;
+
+	      bgp_unlock_node (rn);
+
+	      return min;
+	    }
+
+	  paddr.s_addr = 0;
+	}
+      while ((rn = bgp_route_next (rn)) != NULL);
+    }
+  return NULL;
+}
+
+u_char *
+bgp4PathAttrTable (struct variable *v, oid name[], size_t *length,
+		   int exact, size_t *var_len, WriteMethod **write_method)
+{
+  struct bgp *bgp;
+  struct bgp_info *binfo;
+  struct prefix_ipv4 addr;
+  
+  bgp = bgp_get_default ();
+  if (! bgp)
+    return NULL;
+
+  memset (&addr, 0, sizeof (struct prefix_ipv4));
+
+  binfo = bgp4PathAttrLookup (v, name, length, bgp, &addr, exact);
+  if (! binfo)
+    return NULL;
+
+  switch (v->magic)
+    {
+    case BGP4PATHATTRPEER:	/* 1 */
+      return SNMP_IPADDRESS (binfo->peer->su.sin.sin_addr);
+      break;
+    case BGP4PATHATTRIPADDRPREFIXLEN: /* 2 */
+      return SNMP_INTEGER (addr.prefixlen);
+      break;
+    case BGP4PATHATTRIPADDRPREFIX: /* 3 */
+      return SNMP_IPADDRESS (addr.prefix);
+      break;
+    case BGP4PATHATTRORIGIN:	/* 4 */
+      return SNMP_INTEGER (binfo->attr->origin);
+      break;
+    case BGP4PATHATTRASPATHSEGMENT: /* 5 */
+      *var_len = binfo->attr->aspath->length;
+      return (u_char *) binfo->attr->aspath->data;
+      break;
+    case BGP4PATHATTRNEXTHOP:	/* 6 */
+      return SNMP_IPADDRESS (binfo->attr->nexthop);
+      break;
+    case BGP4PATHATTRMULTIEXITDISC: /* 7 */
+      return SNMP_INTEGER (binfo->attr->med);
+      break;
+    case BGP4PATHATTRLOCALPREF:	/* 8 */
+      return SNMP_INTEGER (binfo->attr->local_pref);
+      break;
+    case BGP4PATHATTRATOMICAGGREGATE: /* 9 */
+      return SNMP_INTEGER (1);
+      break;
+    case BGP4PATHATTRAGGREGATORAS: /* 10 */
+      return SNMP_INTEGER (binfo->attr->aggregator_as);
+      break;
+    case BGP4PATHATTRAGGREGATORADDR: /* 11 */
+      return SNMP_IPADDRESS (binfo->attr->aggregator_addr);
+      break;
+    case BGP4PATHATTRCALCLOCALPREF: /* 12 */
+      return SNMP_INTEGER (-1);
+      break;
+    case BGP4PATHATTRBEST:	/* 13 */
+#define BGP4_PathAttrBest_false 1
+#define BGP4_PathAttrBest_true  2
+      if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))
+	return SNMP_INTEGER (BGP4_PathAttrBest_true);
+      else
+	return SNMP_INTEGER (BGP4_PathAttrBest_false);
+      break;
+    case BGP4PATHATTRUNKNOWN:	/* 14 */
+      *var_len = 0;
+      return NULL;
+      break;
+    }
+  return NULL;
+}
+
+/* BGP Traps. */
+struct trap_object bgpTrapList[] =
+{
+  {bgpPeerTable, 3, {3, 1, BGPPEERREMOTEADDR}},
+  {bgpPeerTable, 3, {3, 1, BGPPEERLASTERROR}},
+  {bgpPeerTable, 3, {3, 1, BGPPEERSTATE}}
+};
+
+void
+bgpTrapEstablished (struct peer *peer)
+{
+  int ret;
+  struct in_addr addr;
+  oid index[sizeof (oid) * IN_ADDR_SIZE];
+
+  ret = inet_aton (peer->host, &addr);
+  if (ret == 0)
+    return;
+
+  oid_copy_addr (index, &addr, IN_ADDR_SIZE);
+
+  smux_trap (bgp_oid, sizeof bgp_oid / sizeof (oid),
+	     index, IN_ADDR_SIZE,
+	     bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object),
+	     bm->start_time - time (NULL));
+}
+
+void
+bgpTrapBackwardTransition (struct peer *peer)
+{
+  int ret;
+  struct in_addr addr;
+  oid index[sizeof (oid) * IN_ADDR_SIZE];
+
+  ret = inet_aton (peer->host, &addr);
+  if (ret == 0)
+    return;
+
+  oid_copy_addr (index, &addr, IN_ADDR_SIZE);
+
+  smux_trap (bgp_oid, sizeof bgp_oid / sizeof (oid),
+	     index, IN_ADDR_SIZE,
+	     bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object),
+	     bm->start_time - time (NULL));
+}
+
+void
+bgp_snmp_init ()
+{
+  smux_init (bgpd_oid, sizeof bgpd_oid / sizeof (oid));
+  REGISTER_MIB("mibII/bgp", bgp_variables, variable, bgp_oid);
+  smux_start ();
+}
+#endif /* HAVE_SNMP */
diff --git a/bgpd/bgp_snmp.h b/bgpd/bgp_snmp.h
new file mode 100644
index 0000000..a8af032
--- /dev/null
+++ b/bgpd/bgp_snmp.h
@@ -0,0 +1,23 @@
+/* BGP4 SNMP support
+   Copyright (C) 1999, 2000 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+void bgp_snmp_init ();
+void bgpTrapEstablished (struct peer *);
+void bgpTrapBackwardTransition (struct peer *);
diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c
new file mode 100644
index 0000000..a2a3c97
--- /dev/null
+++ b/bgpd/bgp_table.c
@@ -0,0 +1,489 @@
+/* BGP routing table
+   Copyright (C) 1998, 2001 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "prefix.h"
+#include "memory.h"
+#include "sockunion.h"
+#include "vty.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_table.h"
+
+void bgp_node_delete (struct bgp_node *);
+void bgp_table_free (struct bgp_table *);
+
+struct bgp_table *
+bgp_table_init (void)
+{
+  struct bgp_table *rt;
+
+  rt = XMALLOC (MTYPE_BGP_TABLE, sizeof (struct bgp_table));
+  memset (rt, 0, sizeof (struct bgp_table));
+  return rt;
+}
+
+void
+bgp_table_finish (struct bgp_table *rt)
+{
+  bgp_table_free (rt);
+}
+
+struct bgp_node *
+bgp_node_create ()
+{
+  struct bgp_node *rn;
+
+  rn = (struct bgp_node *) XMALLOC (MTYPE_BGP_NODE, sizeof (struct bgp_node));
+  memset (rn, 0, sizeof (struct bgp_node));
+  return rn;
+}
+
+/* Allocate new route node with prefix set. */
+struct bgp_node *
+bgp_node_set (struct bgp_table *table, struct prefix *prefix)
+{
+  struct bgp_node *node;
+  
+  node = bgp_node_create ();
+
+  prefix_copy (&node->p, prefix);
+  node->table = table;
+
+  return node;
+}
+
+/* Free route node. */
+void
+bgp_node_free (struct bgp_node *node)
+{
+  XFREE (MTYPE_BGP_NODE, node);
+}
+
+/* Free route table. */
+void
+bgp_table_free (struct bgp_table *rt)
+{
+  struct bgp_node *tmp_node;
+  struct bgp_node *node;
+ 
+  if (rt == NULL)
+    return;
+
+  node = rt->top;
+
+  while (node)
+    {
+      if (node->l_left)
+	{
+	  node = node->l_left;
+	  continue;
+	}
+
+      if (node->l_right)
+	{
+	  node = node->l_right;
+	  continue;
+	}
+
+      tmp_node = node;
+      node = node->parent;
+
+      if (node != NULL)
+	{
+	  if (node->l_left == tmp_node)
+	    node->l_left = NULL;
+	  else
+	    node->l_right = NULL;
+
+	  bgp_node_free (tmp_node);
+	}
+      else
+	{
+	  bgp_node_free (tmp_node);
+	  break;
+	}
+    }
+ 
+  XFREE (MTYPE_BGP_TABLE, rt);
+  return;
+}
+
+/* Utility mask array. */
+static u_char maskbit[] = 
+{
+  0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
+};
+
+/* Common prefix route genaration. */
+static void
+route_common (struct prefix *n, struct prefix *p, struct prefix *new)
+{
+  int i;
+  u_char diff;
+  u_char mask;
+
+  u_char *np = (u_char *)&n->u.prefix;
+  u_char *pp = (u_char *)&p->u.prefix;
+  u_char *newp = (u_char *)&new->u.prefix;
+
+  for (i = 0; i < p->prefixlen / 8; i++)
+    {
+      if (np[i] == pp[i])
+	newp[i] = np[i];
+      else
+	break;
+    }
+
+  new->prefixlen = i * 8;
+
+  if (new->prefixlen != p->prefixlen)
+    {
+      diff = np[i] ^ pp[i];
+      mask = 0x80;
+      while (new->prefixlen < p->prefixlen && !(mask & diff))
+	{
+	  mask >>= 1;
+	  new->prefixlen++;
+	}
+      newp[i] = np[i] & maskbit[new->prefixlen % 8];
+    }
+}
+
+/* Macro version of check_bit (). */
+#define CHECK_BIT(X,P) ((((u_char *)(X))[(P) / 8]) >> (7 - ((P) % 8)) & 1)
+
+/* Check bit of the prefix. */
+static int
+check_bit (u_char *prefix, u_char prefixlen)
+{
+  int offset;
+  int shift;
+  u_char *p = (u_char *)prefix;
+
+  assert (prefixlen <= 128);
+
+  offset = prefixlen / 8;
+  shift = 7 - (prefixlen % 8);
+  
+  return (p[offset] >> shift & 1);
+}
+
+/* Macro version of set_link (). */
+#define SET_LINK(X,Y) (X)->link[CHECK_BIT(&(Y)->prefix,(X)->prefixlen)] = (Y);\
+                      (Y)->parent = (X)
+
+static void
+set_link (struct bgp_node *node, struct bgp_node *new)
+{
+  int bit;
+    
+  bit = check_bit (&new->p.u.prefix, node->p.prefixlen);
+
+  assert (bit == 0 || bit == 1);
+
+  node->link[bit] = new;
+  new->parent = node;
+}
+
+/* Lock node. */
+struct bgp_node *
+bgp_lock_node (struct bgp_node *node)
+{
+  node->lock++;
+  return node;
+}
+
+/* Unlock node. */
+void
+bgp_unlock_node (struct bgp_node *node)
+{
+  node->lock--;
+
+  if (node->lock == 0)
+    bgp_node_delete (node);
+}
+
+/* Find matched prefix. */
+struct bgp_node *
+bgp_node_match (struct bgp_table *table, struct prefix *p)
+{
+  struct bgp_node *node;
+  struct bgp_node *matched;
+
+  matched = NULL;
+  node = table->top;
+
+  /* Walk down tree.  If there is matched route then store it to
+     matched. */
+  while (node && node->p.prefixlen <= p->prefixlen && 
+	 prefix_match (&node->p, p))
+    {
+      if (node->info)
+	matched = node;
+      node = node->link[check_bit(&p->u.prefix, node->p.prefixlen)];
+    }
+
+  /* If matched route found, return it. */
+  if (matched)
+    return bgp_lock_node (matched);
+
+  return NULL;
+}
+
+struct bgp_node *
+bgp_node_match_ipv4 (struct bgp_table *table, struct in_addr *addr)
+{
+  struct prefix_ipv4 p;
+
+  memset (&p, 0, sizeof (struct prefix_ipv4));
+  p.family = AF_INET;
+  p.prefixlen = IPV4_MAX_PREFIXLEN;
+  p.prefix = *addr;
+
+  return bgp_node_match (table, (struct prefix *) &p);
+}
+
+#ifdef HAVE_IPV6
+struct bgp_node *
+bgp_node_match_ipv6 (struct bgp_table *table, struct in6_addr *addr)
+{
+  struct prefix_ipv6 p;
+
+  memset (&p, 0, sizeof (struct prefix_ipv6));
+  p.family = AF_INET6;
+  p.prefixlen = IPV6_MAX_PREFIXLEN;
+  p.prefix = *addr;
+
+  return bgp_node_match (table, (struct prefix *) &p);
+}
+#endif /* HAVE_IPV6 */
+
+/* Lookup same prefix node.  Return NULL when we can't find route. */
+struct bgp_node *
+bgp_node_lookup (struct bgp_table *table, struct prefix *p)
+{
+  struct bgp_node *node;
+
+  node = table->top;
+
+  while (node && node->p.prefixlen <= p->prefixlen && 
+	 prefix_match (&node->p, p))
+    {
+      if (node->p.prefixlen == p->prefixlen && node->info)
+	return bgp_lock_node (node);
+
+      node = node->link[check_bit(&p->u.prefix, node->p.prefixlen)];
+    }
+
+  return NULL;
+}
+
+/* Add node to routing table. */
+struct bgp_node *
+bgp_node_get (struct bgp_table *table, struct prefix *p)
+{
+  struct bgp_node *new;
+  struct bgp_node *node;
+  struct bgp_node *match;
+
+  match = NULL;
+  node = table->top;
+  while (node && node->p.prefixlen <= p->prefixlen && 
+	 prefix_match (&node->p, p))
+    {
+      if (node->p.prefixlen == p->prefixlen)
+	{
+	  bgp_lock_node (node);
+	  return node;
+	}
+      match = node;
+      node = node->link[check_bit(&p->u.prefix, node->p.prefixlen)];
+    }
+
+  if (node == NULL)
+    {
+      new = bgp_node_set (table, p);
+      if (match)
+	set_link (match, new);
+      else
+	table->top = new;
+    }
+  else
+    {
+      new = bgp_node_create ();
+      route_common (&node->p, p, &new->p);
+      new->p.family = p->family;
+      new->table = table;
+      set_link (new, node);
+
+      if (match)
+	set_link (match, new);
+      else
+	table->top = new;
+
+      if (new->p.prefixlen != p->prefixlen)
+	{
+	  match = new;
+	  new = bgp_node_set (table, p);
+	  set_link (match, new);
+	}
+    }
+  bgp_lock_node (new);
+  
+  return new;
+}
+
+/* Delete node from the routing table. */
+void
+bgp_node_delete (struct bgp_node *node)
+{
+  struct bgp_node *child;
+  struct bgp_node *parent;
+
+  assert (node->lock == 0);
+  assert (node->info == NULL);
+
+  if (node->l_left && node->l_right)
+    return;
+
+  if (node->l_left)
+    child = node->l_left;
+  else
+    child = node->l_right;
+
+  parent = node->parent;
+
+  if (child)
+    child->parent = parent;
+
+  if (parent)
+    {
+      if (parent->l_left == node)
+	parent->l_left = child;
+      else
+	parent->l_right = child;
+    }
+  else
+    node->table->top = child;
+
+  bgp_node_free (node);
+
+  /* If parent node is stub then delete it also. */
+  if (parent && parent->lock == 0)
+    bgp_node_delete (parent);
+}
+
+/* Get fist node and lock it.  This function is useful when one want
+   to lookup all the node exist in the routing table. */
+struct bgp_node *
+bgp_table_top (struct bgp_table *table)
+{
+  /* If there is no node in the routing table return NULL. */
+  if (table->top == NULL)
+    return NULL;
+
+  /* Lock the top node and return it. */
+  bgp_lock_node (table->top);
+  return table->top;
+}
+
+/* Unlock current node and lock next node then return it. */
+struct bgp_node *
+bgp_route_next (struct bgp_node *node)
+{
+  struct bgp_node *next;
+  struct bgp_node *start;
+
+  /* Node may be deleted from bgp_unlock_node so we have to preserve
+     next node's pointer. */
+
+  if (node->l_left)
+    {
+      next = node->l_left;
+      bgp_lock_node (next);
+      bgp_unlock_node (node);
+      return next;
+    }
+  if (node->l_right)
+    {
+      next = node->l_right;
+      bgp_lock_node (next);
+      bgp_unlock_node (node);
+      return next;
+    }
+
+  start = node;
+  while (node->parent)
+    {
+      if (node->parent->l_left == node && node->parent->l_right)
+	{
+	  next = node->parent->l_right;
+	  bgp_lock_node (next);
+	  bgp_unlock_node (start);
+	  return next;
+	}
+      node = node->parent;
+    }
+  bgp_unlock_node (start);
+  return NULL;
+}
+
+/* Unlock current node and lock next node until limit. */
+struct bgp_node *
+bgp_route_next_until (struct bgp_node *node, struct bgp_node *limit)
+{
+  struct bgp_node *next;
+  struct bgp_node *start;
+
+  /* Node may be deleted from bgp_unlock_node so we have to preserve
+     next node's pointer. */
+
+  if (node->l_left)
+    {
+      next = node->l_left;
+      bgp_lock_node (next);
+      bgp_unlock_node (node);
+      return next;
+    }
+  if (node->l_right)
+    {
+      next = node->l_right;
+      bgp_lock_node (next);
+      bgp_unlock_node (node);
+      return next;
+    }
+
+  start = node;
+  while (node->parent && node != limit)
+    {
+      if (node->parent->l_left == node && node->parent->l_right)
+	{
+	  next = node->parent->l_right;
+	  bgp_lock_node (next);
+	  bgp_unlock_node (start);
+	  return next;
+	}
+      node = node->parent;
+    }
+  bgp_unlock_node (start);
+  return NULL;
+}
diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h
new file mode 100644
index 0000000..52eb6a4
--- /dev/null
+++ b/bgpd/bgp_table.h
@@ -0,0 +1,65 @@
+/* BGP routing table
+   Copyright (C) 1998, 2001 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+struct bgp_table
+{
+  struct bgp_node *top;
+};
+
+struct bgp_node
+{
+  struct prefix p;
+
+  struct bgp_table *table;
+  struct bgp_node *parent;
+  struct bgp_node *link[2];
+#define l_left   link[0]
+#define l_right  link[1]
+
+  unsigned int lock;
+
+  void *info;
+
+  struct bgp_adj_out *adj_out;
+
+  struct bgp_adj_in *adj_in;
+
+  void *aggregate;
+
+  struct bgp_node *prn;
+};
+
+struct bgp_table *bgp_table_init (void);
+void bgp_table_finish (struct bgp_table *);
+void bgp_unlock_node (struct bgp_node *node);
+void bgp_node_delete (struct bgp_node *node);
+struct bgp_node *bgp_table_top (struct bgp_table *);
+struct bgp_node *bgp_route_next (struct bgp_node *);
+struct bgp_node *bgp_route_next_until (struct bgp_node *, struct bgp_node *);
+struct bgp_node *bgp_node_get (struct bgp_table *, struct prefix *);
+struct bgp_node *bgp_node_lookup (struct bgp_table *, struct prefix *);
+struct bgp_node *bgp_lock_node (struct bgp_node *node);
+struct bgp_node *bgp_node_match (struct bgp_table *, struct prefix *);
+struct bgp_node *bgp_node_match_ipv4 (struct bgp_table *,
+					  struct in_addr *);
+#ifdef HAVE_IPV6
+struct bgp_node *bgp_node_match_ipv6 (struct bgp_table *,
+					  struct in6_addr *);
+#endif /* HAVE_IPV6 */
diff --git a/bgpd/bgp_view.c b/bgpd/bgp_view.c
new file mode 100644
index 0000000..795d155
--- /dev/null
+++ b/bgpd/bgp_view.c
@@ -0,0 +1,258 @@
+/*
+ * $Id: bgp_view.c,v 1.1 2002/12/13 20:15:29 paul Exp $
+ *
+ * Multiple view function for route server.
+ * Copyright (C) 1997 Kunihiro Ishiguro
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#include <zebra.h>
+
+#include "linklist.h"
+#include "vector.h"
+#include "vty.h"
+#include "command.h"
+#include "prefix.h"
+#include "zebra/zebra.h"
+#include "table.h"
+#include "log.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_dump.h"
+#include "bgpd/bgp_aspath.h"
+
+/* Static configuration of BGP annoucement. */
+struct route_table *bgp_static_ipv4;
+#ifdef HAVE_IPV6
+struct route_table *bgp_static_ipv6;
+#endif /* HAVE_IPV6 */
+
+/* Static annoucement peer. */
+struct peer *static_peer;
+
+/* Default value setting flag */
+#define VAL_LOCAL_PREF 0x01
+#define VAL_MED        0x02
+#define VAL_NEXT_HOP   0x04
+
+DEFUN (default_attr_localpref,
+       default_attr_localpref_cmd,
+       "default-attr local-pref NUMBER",
+       "Set default local preference value\n"
+       "Set default local preference value\n"
+       "Value\n")
+{
+  struct bgp *bgp;
+  long lpref;
+
+  bgp = (struct bgp *) vty->index;
+
+  lpref = strtol (argv[0], NULL, 10);
+
+  bgp->def |= VAL_LOCAL_PREF;
+  bgp->localpref = lpref;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_default_attr_localpref,
+       no_default_attr_localpref_cmd,
+       "no default-attr local-pref NUMBER",
+       NO_STR
+       "Unset default local preference value\n"
+       "Unset default local preference value\n"
+       "Value\n")
+{
+  struct bgp *bgp;
+
+  bgp = (struct bgp *) vty->index;
+
+  bgp->def &= ~DEFAULT_LOCAL_PREF;
+  bgp->localpref = 0;
+
+  return CMD_SUCCESS;
+}
+
+#ifdef HAVE_IPV6
+/* Network configuration for IPv6. */
+int
+bgp_network_config_ipv6 (struct vty *vty, char *address_str)
+{
+  int ret;
+  struct prefix p;
+  struct route_node *node;
+  struct bgp_info *bgp_info;
+
+  ret = str2prefix_ipv6 (address_str, (struct prefix_ipv6 *) &p);
+  if (!ret)
+    {
+      vty_out (vty, "Please specify valid address\r\n");
+      return CMD_WARNING;
+    }
+
+  apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
+  
+  node = route_node_get (bgp_static_ipv6, &p);
+  if (node->info)
+    {
+      vty_out (vty, "There is already same static announcement.\r\n");
+      route_unlock_node (node);
+      return CMD_WARNING;
+    }
+
+  bgp_info = bgp_info_new ();
+  bgp_info->type = ZEBRA_ROUTE_STATIC;
+  bgp_info->peer = static_peer;
+  bgp_info->attr = bgp_attr_make_default ();
+  node->info = bgp_info;
+
+  nlri_process (&p, bgp_info);
+
+  return CMD_SUCCESS;
+}
+#endif
+
+/* Configure static BGP network. */
+DEFUN (bgp_network,
+       bgp_network_cmd,
+       "network PREFIX",
+       "Announce network setup\n"
+       "Static network for bgp announcement\n")
+{
+  int ret;
+  struct bgp *bgp;
+  struct prefix p;
+  struct route_node *node;
+  struct bgp_info *bgp_info;
+
+  bgp = (struct bgp *) vty->index;
+
+  ret = str2prefix_ipv4 (argv[0], (struct prefix_ipv4 *) &p);
+  if (!ret)
+    {
+#ifdef HAVE_IPV6
+      return bgp_network_config_ipv6 (vty, argv[0]);
+#endif /* HAVE_IPV6 */
+
+      vty_out (vty, "Please specify address by a.b.c.d/mask\r\n");
+      return CMD_WARNING;
+    }
+
+  /* Make sure mask is applied. */
+  apply_mask ((struct prefix_ipv4 *) &p);
+
+  node = route_node_get (bgp_static_ipv4, &p);
+  if (node->info)
+    {
+      vty_out (vty, "There is already same static announcement.\r\n");
+      route_unlock_node (node);
+      return CMD_WARNING;
+    }
+
+  bgp_info = bgp_info_new ();
+  bgp_info->type = ZEBRA_ROUTE_STATIC;
+  bgp_info->peer = static_peer;
+  bgp_info->attr = bgp_attr_make_default ();
+  node->info = bgp_info;
+
+  nlri_process (&p, bgp_info);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_network,
+       no_bgp_network_cmd,
+       "no network PREFIX",
+       NO_STR
+       "Announce network setup\n"
+       "Delete static network for bgp announcement\n")
+{
+  int ret;
+  struct bgp *bgp;
+  struct route_node *np;
+  struct prefix_ipv4 p;
+
+  bgp = (struct bgp *) vty->index;
+
+  ret = str2prefix_ipv4 (argv[0], &p);
+  if (!ret)
+    {
+      vty_out (vty, "Please specify address by a.b.c.d/mask\r\n");
+      return CMD_WARNING;
+    }
+
+  apply_mask (&p);
+
+  np = route_node_get (bgp_static_ipv4, (struct prefix *) &p);
+  if (!np->info)
+    {
+      vty_out (vty, "Can't find specified static route configuration.\r\n");
+      route_unlock_node (np);
+      return CMD_WARNING;
+    }
+  nlri_delete (static_peer, (struct prefix *) &p);
+
+  /* bgp_attr_free (np->info); */
+  np->info = NULL;
+
+  route_unlock_node (np);
+
+  return CMD_SUCCESS;
+}
+
+int
+config_write_network (struct vty *vty, struct bgp *bgp)
+{
+  struct route_node *node;
+  struct bgp_route *route;
+  char buf[BUFSIZ];
+  
+  for (node = route_top (bgp_static_ipv4); node; node = route_next (node)) 
+    for (route = node->info; route; route = route->next)
+      vty_out (vty, " network %s/%d%s", 
+	       inet_ntoa (node->p.u.prefix4), node->p.prefixlen, VTY_NEWLINE);
+#ifdef HAVE_IPV6
+  for (node = route_top (bgp_static_ipv6); node; node = route_next (node)) 
+    for (route = node->info; route; route = route->next)
+      vty_out (vty, " network %s/%d%s", 
+	       inet_ntop (AF_INET6, &node->p.u.prefix6, buf, BUFSIZ),
+	       node->p.prefixlen, VTY_NEWLINE);
+#endif /* HAVE_IPV6 */
+
+  return 0;
+}
+
+void
+view_init ()
+{
+  bgp_static_ipv4 = route_table_init ();
+#ifdef HAVE_IPV6
+  bgp_static_ipv6 = route_table_init ();
+#endif /* HAVE_IPV6 */
+
+  static_peer = peer_new ();
+  static_peer->host = "Static annucement";
+
+  install_element (BGP_NODE, &bgp_network_cmd);
+  install_element (BGP_NODE, &no_bgp_network_cmd);
+  install_element (BGP_NODE, &default_attr_localpref_cmd);
+  install_element (BGP_NODE, &no_default_attr_localpref_cmd);
+}
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
new file mode 100644
index 0000000..c1bae93
--- /dev/null
+++ b/bgpd/bgp_vty.c
@@ -0,0 +1,9416 @@
+/* BGP VTY interface.
+   Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "command.h"
+#include "prefix.h"
+#include "plist.h"
+#include "buffer.h"
+#include "linklist.h"
+#include "stream.h"
+#include "thread.h"
+#include "log.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_aspath.h"
+#include "bgpd/bgp_community.h"
+#include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_mplsvpn.h"
+#include "bgpd/bgp_open.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_zebra.h"
+
+/* Utility function to get address family from current node.  */
+afi_t
+bgp_node_afi (struct vty *vty)
+{
+  if (vty->node == BGP_IPV6_NODE)
+    return AFI_IP6;
+  return AFI_IP;
+}
+
+/* Utility function to get subsequent address family from current
+   node.  */
+safi_t
+bgp_node_safi (struct vty *vty)
+{
+  if (vty->node == BGP_VPNV4_NODE)
+    return SAFI_MPLS_VPN;
+  if (vty->node == BGP_IPV4M_NODE)
+    return SAFI_MULTICAST;
+  return SAFI_UNICAST;
+}
+
+int
+peer_address_self_check (union sockunion *su)
+{
+  struct interface *ifp = NULL;
+
+  if (su->sa.sa_family == AF_INET)
+    ifp = if_lookup_by_ipv4_exact (&su->sin.sin_addr);
+#ifdef HAVE_IPV6
+  else if (su->sa.sa_family == AF_INET6)
+    ifp = if_lookup_by_ipv6_exact (&su->sin6.sin6_addr);
+#endif /* HAVE IPV6 */
+
+  if (ifp)
+    return 1;
+
+  return 0;
+}
+
+/* Utility function for looking up peer from VTY.  */
+struct peer *
+peer_lookup_vty (struct vty *vty, char *ip_str)
+{
+  int ret;
+  struct bgp *bgp;
+  union sockunion su;
+  struct peer *peer;
+
+  bgp = vty->index;
+
+  ret = str2sockunion (ip_str, &su);
+  if (ret < 0)
+    {
+      vty_out (vty, "%% Malformed address: %s%s", ip_str, VTY_NEWLINE);
+      return NULL;
+    }
+
+  peer = peer_lookup (bgp, &su);
+  if (! peer)
+    {
+      vty_out (vty, "%% Specify remote-as or peer-group commands first%s", VTY_NEWLINE);
+      return NULL;
+    }
+  return peer;
+}
+
+/* Utility function for looking up peer or peer group.  */
+struct peer *
+peer_and_group_lookup_vty (struct vty *vty, char *peer_str)
+{
+  int ret;
+  struct bgp *bgp;
+  union sockunion su;
+  struct peer *peer;
+  struct peer_group *group;
+
+  bgp = vty->index;
+
+  ret = str2sockunion (peer_str, &su);
+  if (ret == 0)
+    {
+      peer = peer_lookup (bgp, &su);
+      if (peer)
+	return peer;
+    }
+  else
+    {
+      group = peer_group_lookup (bgp, peer_str);
+      if (group)
+	return group->conf;
+    }
+
+  vty_out (vty, "%% Specify remote-as or peer-group commands first%s",
+	   VTY_NEWLINE);
+
+  return NULL;
+}
+
+int
+bgp_vty_return (struct vty *vty, int ret)
+{
+  char *str = NULL;
+
+  switch (ret)
+    {
+    case BGP_ERR_INVALID_VALUE:
+      str = "Invalid value";
+      break;
+    case BGP_ERR_INVALID_FLAG:
+      str = "Invalid flag";
+      break;
+    case BGP_ERR_PEER_INACTIVE:
+      str = "Activate the neighbor for the address family first";
+      break;
+    case BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER:
+      str = "Invalid command for a peer-group member";
+      break;
+    case BGP_ERR_PEER_GROUP_SHUTDOWN:
+      str = "Peer-group has been shutdown. Activate the peer-group first";
+      break;
+    case BGP_ERR_PEER_GROUP_HAS_THE_FLAG:
+      str = "This peer is a peer-group member.  Please change peer-group configuration";
+      break;
+    case BGP_ERR_PEER_FLAG_CONFLICT:
+      str = "Can't set override-capability and strict-capability-match at the same time";
+      break;
+    case BGP_ERR_PEER_GROUP_MEMBER_EXISTS:
+      str = "No activate for peergroup can be given only if peer-group has no members";
+      break;
+    case BGP_ERR_PEER_BELONGS_TO_GROUP:
+      str = "No activate for an individual peer-group member is invalid";
+      break;
+    case BGP_ERR_PEER_GROUP_AF_UNCONFIGURED:
+      str = "Activate the peer-group for the address family first";
+      break;
+    case BGP_ERR_PEER_GROUP_NO_REMOTE_AS:
+      str = "Specify remote-as or peer-group remote AS first";
+      break;
+    case BGP_ERR_PEER_GROUP_CANT_CHANGE:
+      str = "Cannot change the peer-group. Deconfigure first";
+      break;
+    case BGP_ERR_PEER_GROUP_MISMATCH:
+      str = "Cannot have different peer-group for the neighbor";
+      break;
+    case BGP_ERR_PEER_FILTER_CONFLICT:
+      str = "Prefix/distribute list can not co-exist";
+      break;
+    case BGP_ERR_NOT_INTERNAL_PEER:
+      str = "Invalid command. Not an internal neighbor";
+      break;
+    case BGP_ERR_REMOVE_PRIVATE_AS:
+      str = "Private AS cannot be removed for IBGP peers";
+      break;
+    case BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP:
+      str = "Local-AS allowed only for EBGP peers";
+      break;
+    case BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS:
+      str = "Cannot have local-as same as BGP AS number";
+      break;
+    }
+  if (str)
+    {
+      vty_out (vty, "%% %s%s", str, VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  return CMD_SUCCESS;
+}
+
+/* BGP global configuration.  */
+
+DEFUN (bgp_multiple_instance_func,
+       bgp_multiple_instance_cmd,
+       "bgp multiple-instance",
+       BGP_STR
+       "Enable bgp multiple instance\n")
+{
+  bgp_option_set (BGP_OPT_MULTIPLE_INSTANCE);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_multiple_instance,
+       no_bgp_multiple_instance_cmd,
+       "no bgp multiple-instance",
+       NO_STR
+       BGP_STR
+       "BGP multiple instance\n")
+{
+  int ret;
+
+  ret = bgp_option_unset (BGP_OPT_MULTIPLE_INSTANCE);
+  if (ret < 0)
+    {
+      vty_out (vty, "%% There are more than two BGP instances%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (bgp_config_type,
+       bgp_config_type_cmd,
+       "bgp config-type (cisco|zebra)",
+       BGP_STR
+       "Configuration type\n"
+       "cisco\n"
+       "zebra\n")
+{
+  if (strncmp (argv[0], "c", 1) == 0)
+    bgp_option_set (BGP_OPT_CONFIG_CISCO);
+  else
+    bgp_option_unset (BGP_OPT_CONFIG_CISCO);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_config_type,
+       no_bgp_config_type_cmd,
+       "no bgp config-type",
+       NO_STR
+       BGP_STR
+       "Display configuration type\n")
+{
+  bgp_option_unset (BGP_OPT_CONFIG_CISCO);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_synchronization,
+       no_synchronization_cmd,
+       "no synchronization",
+       NO_STR
+       "Perform IGP synchronization\n")
+{
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_auto_summary,
+       no_auto_summary_cmd,
+       "no auto-summary",
+       NO_STR
+       "Enable automatic network number summarization\n")
+{
+  return CMD_SUCCESS;
+}
+
+/* "router bgp" commands. */
+DEFUN (router_bgp, 
+       router_bgp_cmd, 
+       "router bgp <1-65535>",
+       ROUTER_STR
+       BGP_STR
+       AS_STR)
+{
+  int ret;
+  as_t as;
+  struct bgp *bgp;
+  char *name = NULL;
+
+  VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, 65535);
+
+  if (argc == 2)
+    name = argv[1];
+
+  ret = bgp_get (&bgp, &as, name);
+  switch (ret)
+    {
+    case BGP_ERR_MULTIPLE_INSTANCE_NOT_SET:
+      vty_out (vty, "Please specify 'bgp multiple-instance' first%s", 
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+      break;
+    case BGP_ERR_AS_MISMATCH:
+      vty_out (vty, "BGP is already running; AS is %d%s", as, VTY_NEWLINE);
+      return CMD_WARNING;
+      break;
+    case BGP_ERR_INSTANCE_MISMATCH:
+      vty_out (vty, "BGP view name and AS number mismatch%s", VTY_NEWLINE);
+      vty_out (vty, "BGP instance is already running; AS is %d%s",
+	       as, VTY_NEWLINE);
+      return CMD_WARNING;
+      break;
+    }
+
+  vty->node = BGP_NODE;
+  vty->index = bgp;
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (router_bgp,
+       router_bgp_view_cmd,
+       "router bgp <1-65535> view WORD",
+       ROUTER_STR
+       BGP_STR
+       AS_STR
+       "BGP view\n"
+       "view name\n")
+
+/* "no router bgp" commands. */
+DEFUN (no_router_bgp,
+       no_router_bgp_cmd,
+       "no router bgp <1-65535>",
+       NO_STR
+       ROUTER_STR
+       BGP_STR
+       AS_STR)
+{
+  as_t as;
+  struct bgp *bgp;
+  char *name = NULL;
+
+  VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, 65535);
+
+  if (argc == 2)
+    name = argv[1];
+
+  /* Lookup bgp structure. */
+  bgp = bgp_lookup (as, name);
+  if (! bgp)
+    {
+      vty_out (vty, "%% Can't find BGP instance%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  bgp_delete (bgp);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_router_bgp,
+       no_router_bgp_view_cmd,
+       "no router bgp <1-65535> view WORD",
+       NO_STR
+       ROUTER_STR
+       BGP_STR
+       AS_STR
+       "BGP view\n"
+       "view name\n")
+
+/* BGP router-id.  */
+
+DEFUN (bgp_router_id,
+       bgp_router_id_cmd,
+       "bgp router-id A.B.C.D",
+       BGP_STR
+       "Override configured router identifier\n"
+       "Manually configured router identifier\n")
+{
+  int ret;
+  struct in_addr id;
+  struct bgp *bgp;
+
+  bgp = vty->index;
+
+  ret = inet_aton (argv[0], &id);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed bgp router identifier%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  bgp_router_id_set (bgp, &id);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_router_id,
+       no_bgp_router_id_cmd,
+       "no bgp router-id",
+       NO_STR
+       BGP_STR
+       "Override configured router identifier\n")
+{
+  int ret;
+  struct in_addr id;
+  struct bgp *bgp;
+
+  bgp = vty->index;
+
+  if (argc == 1)
+    {
+      ret = inet_aton (argv[0], &id);
+      if (! ret)
+	{
+	  vty_out (vty, "%% Malformed BGP router identifier%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	}
+
+      if (! IPV4_ADDR_SAME (&bgp->router_id, &id))
+	{
+	  vty_out (vty, "%% BGP router-id doesn't match%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	}
+    }
+
+  bgp_router_id_unset (bgp);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_bgp_router_id,
+       no_bgp_router_id_val_cmd,
+       "no bgp router-id A.B.C.D",
+       NO_STR
+       BGP_STR
+       "Override configured router identifier\n"
+       "Manually configured router identifier\n")
+
+/* BGP Cluster ID.  */
+
+DEFUN (bgp_cluster_id,
+       bgp_cluster_id_cmd,
+       "bgp cluster-id A.B.C.D",
+       BGP_STR
+       "Configure Route-Reflector Cluster-id\n"
+       "Route-Reflector Cluster-id in IP address format\n")
+{
+  int ret;
+  struct bgp *bgp;
+  struct in_addr cluster;
+
+  bgp = vty->index;
+
+  ret = inet_aton (argv[0], &cluster);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed bgp cluster identifier%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  bgp_cluster_id_set (bgp, &cluster);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (bgp_cluster_id,
+       bgp_cluster_id32_cmd,
+       "bgp cluster-id <1-4294967295>",
+       BGP_STR
+       "Configure Route-Reflector Cluster-id\n"
+       "Route-Reflector Cluster-id as 32 bit quantity\n")
+
+DEFUN (no_bgp_cluster_id,
+       no_bgp_cluster_id_cmd,
+       "no bgp cluster-id",
+       NO_STR
+       BGP_STR
+       "Configure Route-Reflector Cluster-id\n")
+{
+  int ret;
+  struct bgp *bgp;
+  struct in_addr cluster;
+
+  bgp = vty->index;
+
+  if (argc == 1)
+    {
+      ret = inet_aton (argv[0], &cluster);
+      if (! ret)
+	{
+	  vty_out (vty, "%% Malformed bgp cluster identifier%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	}
+    }
+
+  bgp_cluster_id_unset (bgp);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_bgp_cluster_id,
+       no_bgp_cluster_id_arg_cmd,
+       "no bgp cluster-id A.B.C.D",
+       NO_STR
+       BGP_STR
+       "Configure Route-Reflector Cluster-id\n"
+       "Route-Reflector Cluster-id in IP address format\n")
+
+DEFUN (bgp_confederation_identifier,
+       bgp_confederation_identifier_cmd,
+       "bgp confederation identifier <1-65535>",
+       "BGP specific commands\n"
+       "AS confederation parameters\n"
+       "AS number\n"
+       "Set routing domain confederation AS\n")
+{
+  struct bgp *bgp;
+  as_t as;
+
+  bgp = vty->index;
+
+  VTY_GET_INTEGER ("AS", as, argv[0]);
+
+  bgp_confederation_id_set (bgp, as);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_confederation_identifier,
+       no_bgp_confederation_identifier_cmd,
+       "no bgp confederation identifier",
+       NO_STR
+       "BGP specific commands\n"
+       "AS confederation parameters\n"
+       "AS number\n")
+{
+  struct bgp *bgp;
+  as_t as;
+
+  bgp = vty->index;
+
+  if (argc == 1)
+    VTY_GET_INTEGER ("AS", as, argv[0]);
+
+  bgp_confederation_id_unset (bgp);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_bgp_confederation_identifier,
+       no_bgp_confederation_identifier_arg_cmd,
+       "no bgp confederation identifier <1-65535>",
+       NO_STR
+       "BGP specific commands\n"
+       "AS confederation parameters\n"
+       "AS number\n"
+       "Set routing domain confederation AS\n")
+
+DEFUN (bgp_confederation_peers,
+       bgp_confederation_peers_cmd,
+       "bgp confederation peers .<1-65535>",
+       "BGP specific commands\n"
+       "AS confederation parameters\n"
+       "Peer ASs in BGP confederation\n"
+       AS_STR)
+{
+  struct bgp *bgp;
+  as_t as;
+  int i;
+
+  bgp = vty->index;
+
+  for (i = 0; i < argc; i++)
+    {
+      VTY_GET_INTEGER_RANGE ("AS", as, argv[i], 1, 65535);
+
+      if (bgp->as == as)
+	{
+	  vty_out (vty, "%% Local member-AS not allowed in confed peer list%s",
+		   VTY_NEWLINE);
+	  continue;
+	}
+
+      bgp_confederation_peers_add (bgp, as);
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_confederation_peers,
+       no_bgp_confederation_peers_cmd,
+       "no bgp confederation peers .<1-65535>",
+       NO_STR
+       "BGP specific commands\n"
+       "AS confederation parameters\n"
+       "Peer ASs in BGP confederation\n"
+       AS_STR)
+{
+  struct bgp *bgp;
+  as_t as;
+  int i;
+
+  bgp = vty->index;
+
+  for (i = 0; i < argc; i++)
+    {
+      VTY_GET_INTEGER_RANGE ("AS", as, argv[i], 1, 65535);
+      
+      bgp_confederation_peers_remove (bgp, as);
+    }
+  return CMD_SUCCESS;
+}
+
+/* BGP timers.  */
+
+DEFUN (bgp_timers,
+       bgp_timers_cmd,
+       "timers bgp <0-65535> <0-65535>",
+       "Adjust routing timers\n"
+       "BGP timers\n"
+       "Keepalive interval\n"
+       "Holdtime\n")
+{
+  struct bgp *bgp;
+  unsigned long keepalive = 0;
+  unsigned long holdtime = 0;
+
+  bgp = vty->index;
+
+  VTY_GET_INTEGER ("keepalive", keepalive, argv[0]);
+  VTY_GET_INTEGER ("holdtime", holdtime, argv[1]);
+
+  /* Holdtime value check. */
+  if (holdtime < 3 && holdtime != 0)
+    {
+      vty_out (vty, "%% hold time value must be either 0 or greater than 3%s",
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  bgp_timers_set (bgp, keepalive, holdtime);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_timers,
+       no_bgp_timers_cmd,
+       "no timers bgp",
+       NO_STR
+       "Adjust routing timers\n"
+       "BGP timers\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  bgp_timers_unset (bgp);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_bgp_timers,
+       no_bgp_timers_arg_cmd,
+       "no timers bgp <0-65535> <0-65535>",
+       NO_STR
+       "Adjust routing timers\n"
+       "BGP timers\n"
+       "Keepalive interval\n"
+       "Holdtime\n")
+
+DEFUN (bgp_client_to_client_reflection,
+       bgp_client_to_client_reflection_cmd,
+       "bgp client-to-client reflection",
+       "BGP specific commands\n"
+       "Configure client to client route reflection\n"
+       "reflection of routes allowed\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  bgp_flag_unset (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_client_to_client_reflection,
+       no_bgp_client_to_client_reflection_cmd,
+       "no bgp client-to-client reflection",
+       NO_STR
+       "BGP specific commands\n"
+       "Configure client to client route reflection\n"
+       "reflection of routes allowed\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  bgp_flag_set (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT);
+  return CMD_SUCCESS;
+}
+
+/* "bgp always-compare-med" configuration. */
+DEFUN (bgp_always_compare_med,
+       bgp_always_compare_med_cmd,
+       "bgp always-compare-med",
+       "BGP specific commands\n"
+       "Allow comparing MED from different neighbors\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  bgp_flag_set (bgp, BGP_FLAG_ALWAYS_COMPARE_MED);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_always_compare_med,
+       no_bgp_always_compare_med_cmd,
+       "no bgp always-compare-med",
+       NO_STR
+       "BGP specific commands\n"
+       "Allow comparing MED from different neighbors\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  bgp_flag_unset (bgp, BGP_FLAG_ALWAYS_COMPARE_MED);
+  return CMD_SUCCESS;
+}
+
+/* "bgp deterministic-med" configuration. */
+DEFUN (bgp_deterministic_med,
+       bgp_deterministic_med_cmd,
+       "bgp deterministic-med",
+       "BGP specific commands\n"
+       "Pick the best-MED path among paths advertised from the neighboring AS\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  bgp_flag_set (bgp, BGP_FLAG_DETERMINISTIC_MED);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_deterministic_med,
+       no_bgp_deterministic_med_cmd,
+       "no bgp deterministic-med",
+       NO_STR
+       "BGP specific commands\n"
+       "Pick the best-MED path among paths advertised from the neighboring AS\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  bgp_flag_unset (bgp, BGP_FLAG_DETERMINISTIC_MED);
+  return CMD_SUCCESS;
+}
+
+/* "bgp fast-external-failover" configuration. */
+DEFUN (bgp_fast_external_failover,
+       bgp_fast_external_failover_cmd,
+       "bgp fast-external-failover",
+       BGP_STR
+       "Immediately reset session if a link to a directly connected external peer goes down\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  bgp_flag_unset (bgp, BGP_FLAG_NO_FAST_EXT_FAILOVER);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_fast_external_failover,
+       no_bgp_fast_external_failover_cmd,
+       "no bgp fast-external-failover",
+       NO_STR
+       BGP_STR
+       "Immediately reset session if a link to a directly connected external peer goes down\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  bgp_flag_set (bgp, BGP_FLAG_NO_FAST_EXT_FAILOVER);
+  return CMD_SUCCESS;
+}
+
+/* "bgp enforce-first-as" configuration. */
+DEFUN (bgp_enforce_first_as,
+       bgp_enforce_first_as_cmd,
+       "bgp enforce-first-as",
+       BGP_STR
+       "Enforce the first AS for EBGP routes\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  bgp_flag_set (bgp, BGP_FLAG_ENFORCE_FIRST_AS);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_enforce_first_as,
+       no_bgp_enforce_first_as_cmd,
+       "no bgp enforce-first-as",
+       NO_STR
+       BGP_STR
+       "Enforce the first AS for EBGP routes\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  bgp_flag_unset (bgp, BGP_FLAG_ENFORCE_FIRST_AS);
+  return CMD_SUCCESS;
+}
+
+/* "bgp bestpath compare-routerid" configuration.  */
+DEFUN (bgp_bestpath_compare_router_id,
+       bgp_bestpath_compare_router_id_cmd,
+       "bgp bestpath compare-routerid",
+       "BGP specific commands\n"
+       "Change the default bestpath selection\n"
+       "Compare router-id for identical EBGP paths\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  bgp_flag_set (bgp, BGP_FLAG_COMPARE_ROUTER_ID);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_bestpath_compare_router_id,
+       no_bgp_bestpath_compare_router_id_cmd,
+       "no bgp bestpath compare-routerid",
+       NO_STR
+       "BGP specific commands\n"
+       "Change the default bestpath selection\n"
+       "Compare router-id for identical EBGP paths\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  bgp_flag_unset (bgp, BGP_FLAG_COMPARE_ROUTER_ID);
+  return CMD_SUCCESS;
+}
+
+/* "bgp bestpath as-path ignore" configuration.  */
+DEFUN (bgp_bestpath_aspath_ignore,
+       bgp_bestpath_aspath_ignore_cmd,
+       "bgp bestpath as-path ignore",
+       "BGP specific commands\n"
+       "Change the default bestpath selection\n"
+       "AS-path attribute\n"
+       "Ignore as-path length in selecting a route\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  bgp_flag_set (bgp, BGP_FLAG_ASPATH_IGNORE);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_bestpath_aspath_ignore,
+       no_bgp_bestpath_aspath_ignore_cmd,
+       "no bgp bestpath as-path ignore",
+       NO_STR
+       "BGP specific commands\n"
+       "Change the default bestpath selection\n"
+       "AS-path attribute\n"
+       "Ignore as-path length in selecting a route\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  bgp_flag_unset (bgp, BGP_FLAG_ASPATH_IGNORE);
+  return CMD_SUCCESS;
+}
+
+/* "bgp bestpath med" configuration. */
+DEFUN (bgp_bestpath_med,
+       bgp_bestpath_med_cmd,
+       "bgp bestpath med (confed|missing-as-worst)",
+       "BGP specific commands\n"
+       "Change the default bestpath selection\n"
+       "MED attribute\n"
+       "Compare MED among confederation paths\n"
+       "Treat missing MED as the least preferred one\n")
+{
+  struct bgp *bgp;
+  
+  bgp = vty->index;
+
+  if (strncmp (argv[0], "confed", 1) == 0)
+    bgp_flag_set (bgp, BGP_FLAG_MED_CONFED);
+  else
+    bgp_flag_set (bgp, BGP_FLAG_MED_MISSING_AS_WORST);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (bgp_bestpath_med2,
+       bgp_bestpath_med2_cmd,
+       "bgp bestpath med confed missing-as-worst",
+       "BGP specific commands\n"
+       "Change the default bestpath selection\n"
+       "MED attribute\n"
+       "Compare MED among confederation paths\n"
+       "Treat missing MED as the least preferred one\n")
+{
+  struct bgp *bgp;
+  
+  bgp = vty->index;
+  bgp_flag_set (bgp, BGP_FLAG_MED_CONFED);
+  bgp_flag_set (bgp, BGP_FLAG_MED_MISSING_AS_WORST);
+  return CMD_SUCCESS;
+}
+
+ALIAS (bgp_bestpath_med2,
+       bgp_bestpath_med3_cmd,
+       "bgp bestpath med missing-as-worst confed",
+       "BGP specific commands\n"
+       "Change the default bestpath selection\n"
+       "MED attribute\n"
+       "Treat missing MED as the least preferred one\n"
+       "Compare MED among confederation paths\n")
+
+DEFUN (no_bgp_bestpath_med,
+       no_bgp_bestpath_med_cmd,
+       "no bgp bestpath med (confed|missing-as-worst)",
+       NO_STR
+       "BGP specific commands\n"
+       "Change the default bestpath selection\n"
+       "MED attribute\n"
+       "Compare MED among confederation paths\n"
+       "Treat missing MED as the least preferred one\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  
+  if (strncmp (argv[0], "confed", 1) == 0)
+    bgp_flag_unset (bgp, BGP_FLAG_MED_CONFED);
+  else
+    bgp_flag_unset (bgp, BGP_FLAG_MED_MISSING_AS_WORST);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_bestpath_med2,
+       no_bgp_bestpath_med2_cmd,
+       "no bgp bestpath med confed missing-as-worst",
+       NO_STR
+       "BGP specific commands\n"
+       "Change the default bestpath selection\n"
+       "MED attribute\n"
+       "Compare MED among confederation paths\n"
+       "Treat missing MED as the least preferred one\n")
+{
+  struct bgp *bgp;
+  
+  bgp = vty->index;
+  bgp_flag_unset (bgp, BGP_FLAG_MED_CONFED);
+  bgp_flag_unset (bgp, BGP_FLAG_MED_MISSING_AS_WORST);
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_bgp_bestpath_med2,
+       no_bgp_bestpath_med3_cmd,
+       "no bgp bestpath med missing-as-worst confed",
+       NO_STR
+       "BGP specific commands\n"
+       "Change the default bestpath selection\n"
+       "MED attribute\n"
+       "Treat missing MED as the least preferred one\n"
+       "Compare MED among confederation paths\n")
+
+/* "no bgp default ipv4-unicast". */
+DEFUN (no_bgp_default_ipv4_unicast,
+       no_bgp_default_ipv4_unicast_cmd,
+       "no bgp default ipv4-unicast",
+       NO_STR
+       "BGP specific commands\n"
+       "Configure BGP defaults\n"
+       "Activate ipv4-unicast for a peer by default\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  bgp_flag_set (bgp, BGP_FLAG_NO_DEFAULT_IPV4);
+  return CMD_SUCCESS;
+}
+
+DEFUN (bgp_default_ipv4_unicast,
+       bgp_default_ipv4_unicast_cmd,
+       "bgp default ipv4-unicast",
+       "BGP specific commands\n"
+       "Configure BGP defaults\n"
+       "Activate ipv4-unicast for a peer by default\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  bgp_flag_unset (bgp, BGP_FLAG_NO_DEFAULT_IPV4);
+  return CMD_SUCCESS;
+}
+
+/* "bgp import-check" configuration.  */
+DEFUN (bgp_network_import_check,
+       bgp_network_import_check_cmd,
+       "bgp network import-check",
+       "BGP specific commands\n"
+       "BGP network command\n"
+       "Check BGP network route exists in IGP\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  bgp_flag_set (bgp, BGP_FLAG_IMPORT_CHECK);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_network_import_check,
+       no_bgp_network_import_check_cmd,
+       "no bgp network import-check",
+       NO_STR
+       "BGP specific commands\n"
+       "BGP network command\n"
+       "Check BGP network route exists in IGP\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  bgp_flag_unset (bgp, BGP_FLAG_IMPORT_CHECK);
+  return CMD_SUCCESS;
+}
+
+DEFUN (bgp_default_local_preference,
+       bgp_default_local_preference_cmd,
+       "bgp default local-preference <0-4294967295>",
+       "BGP specific commands\n"
+       "Configure BGP defaults\n"
+       "local preference (higher=more preferred)\n"
+       "Configure default local preference value\n")
+{
+  struct bgp *bgp;
+  u_int32_t local_pref;
+
+  bgp = vty->index;
+
+  VTY_GET_INTEGER ("local preference", local_pref, argv[0]);
+
+  bgp_default_local_preference_set (bgp, local_pref);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_default_local_preference,
+       no_bgp_default_local_preference_cmd,
+       "no bgp default local-preference",
+       NO_STR
+       "BGP specific commands\n"
+       "Configure BGP defaults\n"
+       "local preference (higher=more preferred)\n")
+{
+  struct bgp *bgp;
+
+  bgp = vty->index;
+  bgp_default_local_preference_unset (bgp);
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_bgp_default_local_preference,
+       no_bgp_default_local_preference_val_cmd,
+       "no bgp default local-preference <0-4294967295>",
+       NO_STR
+       "BGP specific commands\n"
+       "Configure BGP defaults\n"
+       "local preference (higher=more preferred)\n"
+       "Configure default local preference value\n")
+
+static int
+peer_remote_as_vty (struct vty *vty, char *peer_str, char *as_str, afi_t afi,
+		    safi_t safi)
+{
+  int ret;
+  struct bgp *bgp;
+  as_t as;
+  union sockunion su;
+
+  bgp = vty->index;
+
+  /* Get AS number.  */
+  VTY_GET_INTEGER_RANGE ("AS", as, as_str, 1, 65535);
+
+  /* If peer is peer group, call proper function.  */
+  ret = str2sockunion (peer_str, &su);
+  if (ret < 0)
+    {
+      ret = peer_group_remote_as (bgp, peer_str, &as);
+      if (ret < 0)
+	{
+	  vty_out (vty, "%% Create the peer-group first%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	}
+      return CMD_SUCCESS;
+    }
+
+  if (peer_address_self_check (&su))
+    {
+      vty_out (vty, "%% Can not configure the local system as neighbor%s",
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ret = peer_remote_as (bgp, &su, &as, afi, safi);
+
+  /* This peer belongs to peer group.  */
+  switch (ret)
+    {
+    case BGP_ERR_PEER_GROUP_MEMBER:
+      vty_out (vty, "%% Peer-group AS %d. Cannot configure remote-as for member%s", as, VTY_NEWLINE);
+      return CMD_WARNING;
+      break;
+    case BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT:
+      vty_out (vty, "%% The AS# can not be changed from %d to %s, peer-group members must be all internal or all external%s", as, as_str, VTY_NEWLINE);
+      return CMD_WARNING;
+      break;
+    }
+  return bgp_vty_return (vty, ret);
+}
+
+DEFUN (neighbor_remote_as,
+       neighbor_remote_as_cmd,
+       NEIGHBOR_CMD2 "remote-as <1-65535>",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Specify a BGP neighbor\n"
+       AS_STR)
+{
+  return peer_remote_as_vty (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST);
+}
+
+DEFUN (neighbor_peer_group,
+       neighbor_peer_group_cmd,
+       "neighbor WORD peer-group",
+       NEIGHBOR_STR
+       "Neighbor tag\n"
+       "Configure peer-group\n")
+{
+  struct bgp *bgp;
+  struct peer_group *group;
+
+  bgp = vty->index;
+
+  group = peer_group_get (bgp, argv[0]);
+  if (! group)
+    return CMD_WARNING;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_neighbor,
+       no_neighbor_cmd,
+       NO_NEIGHBOR_CMD2,
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2)
+{
+  int ret;
+  union sockunion su;
+  struct peer_group *group;
+  struct peer *peer;
+
+  ret = str2sockunion (argv[0], &su);
+  if (ret < 0)
+    {
+      group = peer_group_lookup (vty->index, argv[0]);
+      if (group)
+	peer_group_delete (group);
+      else
+	{
+	  vty_out (vty, "%% Create the peer-group first%s", VTY_NEWLINE);
+	  return CMD_WARNING;
+	}
+    }
+  else
+    {
+      peer = peer_lookup (vty->index, &su);
+      if (peer)
+	peer_delete (peer);
+    }
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_neighbor,
+       no_neighbor_remote_as_cmd,
+       NO_NEIGHBOR_CMD "remote-as <1-65535>",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR
+       "Specify a BGP neighbor\n"
+       AS_STR)
+
+DEFUN (no_neighbor_peer_group,
+       no_neighbor_peer_group_cmd,
+       "no neighbor WORD peer-group",
+       NO_STR
+       NEIGHBOR_STR
+       "Neighbor tag\n"
+       "Configure peer-group\n")
+{
+  struct peer_group *group;
+
+  group = peer_group_lookup (vty->index, argv[0]);
+  if (group)
+    peer_group_delete (group);
+  else
+    {
+      vty_out (vty, "%% Create the peer-group first%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_neighbor_peer_group_remote_as,
+       no_neighbor_peer_group_remote_as_cmd,
+       "no neighbor WORD remote-as <1-65535>",
+       NO_STR
+       NEIGHBOR_STR
+       "Neighbor tag\n"
+       "Specify a BGP neighbor\n"
+       AS_STR)
+{
+  struct peer_group *group;
+
+  group = peer_group_lookup (vty->index, argv[0]);
+  if (group)
+    peer_group_remote_as_delete (group);
+  else
+    {
+      vty_out (vty, "%% Create the peer-group first%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (neighbor_local_as,
+       neighbor_local_as_cmd,
+       NEIGHBOR_CMD2 "local-as <1-65535>",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Specify a local-as number\n"
+       "AS number used as local AS\n")
+{
+  struct peer *peer;
+  int ret;
+
+  peer = peer_and_group_lookup_vty (vty, argv[0]);
+  if (! peer)
+    return CMD_WARNING;
+
+  ret = peer_local_as_set (peer, atoi (argv[1]), 0);
+  return bgp_vty_return (vty, ret);
+}
+
+DEFUN (neighbor_local_as_no_prepend,
+       neighbor_local_as_no_prepend_cmd,
+       NEIGHBOR_CMD2 "local-as <1-65535> no-prepend",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Specify a local-as number\n"
+       "AS number used as local AS\n"
+       "Do not prepend local-as to updates from ebgp peers\n")
+{
+  struct peer *peer;
+  int ret;
+
+  peer = peer_and_group_lookup_vty (vty, argv[0]);
+  if (! peer)
+    return CMD_WARNING;
+
+  ret = peer_local_as_set (peer, atoi (argv[1]), 1);
+  return bgp_vty_return (vty, ret);
+}
+
+DEFUN (no_neighbor_local_as,
+       no_neighbor_local_as_cmd,
+       NO_NEIGHBOR_CMD2 "local-as",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Specify a local-as number\n")
+{
+  struct peer *peer;
+  int ret;
+
+  peer = peer_and_group_lookup_vty (vty, argv[0]);
+  if (! peer)
+    return CMD_WARNING;
+
+  ret = peer_local_as_unset (peer);
+  return bgp_vty_return (vty, ret);
+}
+
+ALIAS (no_neighbor_local_as,
+       no_neighbor_local_as_val_cmd,
+       NO_NEIGHBOR_CMD2 "local-as <1-65535>",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Specify a local-as number\n"
+       "AS number used as local AS\n")
+
+ALIAS (no_neighbor_local_as,
+       no_neighbor_local_as_val2_cmd,
+       NO_NEIGHBOR_CMD2 "local-as <1-65535> no-prepend",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Specify a local-as number\n"
+       "AS number used as local AS\n"
+       "Do not prepend local-as to updates from ebgp peers\n")
+
+DEFUN (neighbor_activate,
+       neighbor_activate_cmd,
+       NEIGHBOR_CMD2 "activate",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Enable the Address Family for this Neighbor\n")
+{
+  struct peer *peer;
+
+  peer = peer_and_group_lookup_vty (vty, argv[0]);
+  if (! peer)
+    return CMD_WARNING;
+
+  peer_activate (peer, bgp_node_afi (vty), bgp_node_safi (vty));
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_neighbor_activate,
+       no_neighbor_activate_cmd,
+       NO_NEIGHBOR_CMD2 "activate",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Enable the Address Family for this Neighbor\n")
+{
+  int ret;
+  struct peer *peer;
+
+  /* Lookup peer. */
+  peer = peer_and_group_lookup_vty (vty, argv[0]);
+  if (! peer)
+    return CMD_WARNING;
+
+  ret = peer_deactivate (peer, bgp_node_afi (vty), bgp_node_safi (vty));
+
+  return bgp_vty_return (vty, ret);
+}
+
+DEFUN (neighbor_set_peer_group,
+       neighbor_set_peer_group_cmd,
+       NEIGHBOR_CMD "peer-group WORD",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR
+       "Member of the peer-group\n"
+       "peer-group name\n")
+{
+  int ret;
+  as_t as;
+  union sockunion su;
+  struct bgp *bgp;
+  struct peer_group *group;
+
+  bgp = vty->index;
+
+  ret = str2sockunion (argv[0], &su);
+  if (ret < 0)
+    {
+      vty_out (vty, "%% Malformed address: %s%s", argv[0], VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  group = peer_group_lookup (bgp, argv[1]);
+  if (! group)
+    {
+      vty_out (vty, "%% Configure the peer-group first%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (peer_address_self_check (&su))
+    {
+      vty_out (vty, "%% Can not configure the local system as neighbor%s",
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ret = peer_group_bind (bgp, &su, group, bgp_node_afi (vty), 
+			 bgp_node_safi (vty), &as);
+
+  if (ret == BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT)
+    {
+      vty_out (vty, "%% Peer with AS %d cannot be in this peer-group, members must be all internal or all external%s", as, VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_vty_return (vty, ret);
+}
+
+DEFUN (no_neighbor_set_peer_group,
+       no_neighbor_set_peer_group_cmd,
+       NO_NEIGHBOR_CMD "peer-group WORD",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR
+       "Member of the peer-group\n"
+       "peer-group name\n")
+{
+  int ret;
+  struct bgp *bgp;
+  struct peer *peer;
+  struct peer_group *group;
+
+  bgp = vty->index;
+
+  peer = peer_lookup_vty (vty, argv[0]);
+  if (! peer)
+    return CMD_WARNING;
+
+  group = peer_group_lookup (bgp, argv[1]);
+  if (! group)
+    {
+      vty_out (vty, "%% Configure the peer-group first%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  ret = peer_group_unbind (bgp, peer, group, bgp_node_afi (vty),
+			   bgp_node_safi (vty));
+
+  return bgp_vty_return (vty, ret);
+}
+
+int
+peer_flag_modify_vty (struct vty *vty, char *ip_str, u_int16_t flag, int set)
+{
+  int ret;
+  struct peer *peer;
+
+  peer = peer_and_group_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  if (set)
+    ret = peer_flag_set (peer, flag);
+  else
+    ret = peer_flag_unset (peer, flag);
+
+  return bgp_vty_return (vty, ret);
+}
+
+int
+peer_flag_set_vty (struct vty *vty, char *ip_str, u_int16_t flag)
+{
+  return peer_flag_modify_vty (vty, ip_str, flag, 1);
+}
+
+int
+peer_flag_unset_vty (struct vty *vty, char *ip_str, u_int16_t flag)
+{
+  return peer_flag_modify_vty (vty, ip_str, flag, 0);
+}
+
+/* neighbor passive. */
+DEFUN (neighbor_passive,
+       neighbor_passive_cmd,
+       NEIGHBOR_CMD2 "passive",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Don't send open messages to this neighbor\n")
+{
+  return peer_flag_set_vty (vty, argv[0], PEER_FLAG_PASSIVE);
+}
+
+DEFUN (no_neighbor_passive,
+       no_neighbor_passive_cmd,
+       NO_NEIGHBOR_CMD2 "passive",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Don't send open messages to this neighbor\n")
+{
+  return peer_flag_unset_vty (vty, argv[0], PEER_FLAG_PASSIVE);
+}
+
+/* neighbor shutdown. */
+DEFUN (neighbor_shutdown,
+       neighbor_shutdown_cmd,
+       NEIGHBOR_CMD2 "shutdown",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Administratively shut down this neighbor\n")
+{
+  return peer_flag_set_vty (vty, argv[0], PEER_FLAG_SHUTDOWN);
+}
+
+DEFUN (no_neighbor_shutdown,
+       no_neighbor_shutdown_cmd,
+       NO_NEIGHBOR_CMD2 "shutdown",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Administratively shut down this neighbor\n")
+{
+  return peer_flag_unset_vty (vty, argv[0], PEER_FLAG_SHUTDOWN);
+}
+
+/* neighbor capability route-refresh. */
+DEFUN (neighbor_capability_route_refresh,
+       neighbor_capability_route_refresh_cmd,
+       NEIGHBOR_CMD2 "capability route-refresh",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Advertise capability to the peer\n"
+       "Advertise route-refresh capability to this neighbor\n")
+{
+  return peer_flag_unset_vty (vty, argv[0], PEER_FLAG_NO_ROUTE_REFRESH_CAP);
+}
+
+DEFUN (no_neighbor_capability_route_refresh,
+       no_neighbor_capability_route_refresh_cmd,
+       NO_NEIGHBOR_CMD2 "capability route-refresh",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Advertise capability to the peer\n"
+       "Advertise route-refresh capability to this neighbor\n")
+{
+  return peer_flag_set_vty (vty, argv[0], PEER_FLAG_NO_ROUTE_REFRESH_CAP);
+}
+
+/* neighbor capability dynamic. */
+DEFUN (neighbor_capability_dynamic,
+       neighbor_capability_dynamic_cmd,
+       NEIGHBOR_CMD2 "capability dynamic",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Advertise capability to the peer\n"
+       "Advertise dynamic capability to this neighbor\n")
+{
+  return peer_flag_set_vty (vty, argv[0], PEER_FLAG_DYNAMIC_CAPABILITY);
+}
+
+DEFUN (no_neighbor_capability_dynamic,
+       no_neighbor_capability_dynamic_cmd,
+       NO_NEIGHBOR_CMD2 "capability dynamic",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Advertise capability to the peer\n"
+       "Advertise dynamic capability to this neighbor\n")
+{
+  return peer_flag_unset_vty (vty, argv[0], PEER_FLAG_DYNAMIC_CAPABILITY);
+}
+
+/* neighbor dont-capability-negotiate */
+DEFUN (neighbor_dont_capability_negotiate,
+       neighbor_dont_capability_negotiate_cmd,
+       NEIGHBOR_CMD2 "dont-capability-negotiate",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Do not perform capability negotiation\n")
+{
+  return peer_flag_set_vty (vty, argv[0], PEER_FLAG_DONT_CAPABILITY);
+}
+
+DEFUN (no_neighbor_dont_capability_negotiate,
+       no_neighbor_dont_capability_negotiate_cmd,
+       NO_NEIGHBOR_CMD2 "dont-capability-negotiate",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Do not perform capability negotiation\n")
+{
+  return peer_flag_unset_vty (vty, argv[0], PEER_FLAG_DONT_CAPABILITY);
+}
+
+int
+peer_af_flag_modify_vty (struct vty *vty, char *peer_str, afi_t afi,
+			 safi_t safi, u_int16_t flag, int set)
+{
+  int ret;
+  struct peer *peer;
+
+  peer = peer_and_group_lookup_vty (vty, peer_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  if (set)
+    ret = peer_af_flag_set (peer, afi, safi, flag);
+  else
+    ret = peer_af_flag_unset (peer, afi, safi, flag);
+
+  return bgp_vty_return (vty, ret);
+}
+
+int
+peer_af_flag_set_vty (struct vty *vty, char *peer_str, afi_t afi,
+		      safi_t safi, u_int16_t flag)
+{
+  return peer_af_flag_modify_vty (vty, peer_str, afi, safi, flag, 1);
+}
+
+int
+peer_af_flag_unset_vty (struct vty *vty, char *peer_str, afi_t afi,
+			safi_t safi, u_int16_t flag)
+{
+  return peer_af_flag_modify_vty (vty, peer_str, afi, safi, flag, 0);
+}
+
+/* neighbor capability orf prefix-list. */
+DEFUN (neighbor_capability_orf_prefix,
+       neighbor_capability_orf_prefix_cmd,
+       NEIGHBOR_CMD2 "capability orf prefix-list (both|send|receive)",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Advertise capability to the peer\n"
+       "Advertise ORF capability to the peer\n"
+       "Advertise prefixlist ORF capability to this neighbor\n"
+       "Capability to SEND and RECEIVE the ORF to/from this neighbor\n"
+       "Capability to RECEIVE the ORF from this neighbor\n"
+       "Capability to SEND the ORF to this neighbor\n")
+{
+  u_int16_t flag = 0;
+
+  if (strncmp (argv[1], "s", 1) == 0)
+    flag = PEER_FLAG_ORF_PREFIX_SM;
+  else if (strncmp (argv[1], "r", 1) == 0)
+    flag = PEER_FLAG_ORF_PREFIX_RM;
+  else if (strncmp (argv[1], "b", 1) == 0)
+    flag = PEER_FLAG_ORF_PREFIX_SM|PEER_FLAG_ORF_PREFIX_RM;
+  else
+    return CMD_WARNING;
+
+  return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
+			       bgp_node_safi (vty), flag);
+}
+
+DEFUN (no_neighbor_capability_orf_prefix,
+       no_neighbor_capability_orf_prefix_cmd,
+       NO_NEIGHBOR_CMD2 "capability orf prefix-list (both|send|receive)",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Advertise capability to the peer\n"
+       "Advertise ORF capability to the peer\n"
+       "Advertise prefixlist ORF capability to this neighbor\n"
+       "Capability to SEND and RECEIVE the ORF to/from this neighbor\n"
+       "Capability to RECEIVE the ORF from this neighbor\n"
+       "Capability to SEND the ORF to this neighbor\n")
+{
+  u_int16_t flag = 0;
+
+  if (strncmp (argv[1], "s", 1) == 0)
+    flag = PEER_FLAG_ORF_PREFIX_SM;
+  else if (strncmp (argv[1], "r", 1) == 0)
+    flag = PEER_FLAG_ORF_PREFIX_RM;
+  else if (strncmp (argv[1], "b", 1) == 0)
+    flag = PEER_FLAG_ORF_PREFIX_SM|PEER_FLAG_ORF_PREFIX_RM;
+  else
+    return CMD_WARNING;
+
+  return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
+				 bgp_node_safi (vty), flag);
+}
+
+/* neighbor next-hop-self. */
+DEFUN (neighbor_nexthop_self,
+       neighbor_nexthop_self_cmd,
+       NEIGHBOR_CMD2 "next-hop-self",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Disable the next hop calculation for this neighbor\n")
+{
+  return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
+			       bgp_node_safi (vty), PEER_FLAG_NEXTHOP_SELF);
+}
+
+DEFUN (no_neighbor_nexthop_self,
+       no_neighbor_nexthop_self_cmd,
+       NO_NEIGHBOR_CMD2 "next-hop-self",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Disable the next hop calculation for this neighbor\n")
+{
+  return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
+				 bgp_node_safi (vty), PEER_FLAG_NEXTHOP_SELF);
+}
+
+/* neighbor remove-private-AS. */
+DEFUN (neighbor_remove_private_as,
+       neighbor_remove_private_as_cmd,
+       NEIGHBOR_CMD2 "remove-private-AS",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Remove private AS number from outbound updates\n")
+{
+  return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
+			       bgp_node_safi (vty),
+			       PEER_FLAG_REMOVE_PRIVATE_AS);
+}
+
+DEFUN (no_neighbor_remove_private_as,
+       no_neighbor_remove_private_as_cmd,
+       NO_NEIGHBOR_CMD2 "remove-private-AS",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Remove private AS number from outbound updates\n")
+{
+  return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
+				 bgp_node_safi (vty),
+				 PEER_FLAG_REMOVE_PRIVATE_AS);
+}
+
+/* neighbor send-community. */
+DEFUN (neighbor_send_community,
+       neighbor_send_community_cmd,
+       NEIGHBOR_CMD2 "send-community",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Send Community attribute to this neighbor\n")
+{
+  return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
+			       bgp_node_safi (vty),
+			       PEER_FLAG_SEND_COMMUNITY);
+}
+
+DEFUN (no_neighbor_send_community,
+       no_neighbor_send_community_cmd,
+       NO_NEIGHBOR_CMD2 "send-community",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Send Community attribute to this neighbor\n")
+{
+  return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
+				 bgp_node_safi (vty),
+				 PEER_FLAG_SEND_COMMUNITY);
+}
+
+/* neighbor send-community extended. */
+DEFUN (neighbor_send_community_type,
+       neighbor_send_community_type_cmd,
+       NEIGHBOR_CMD2 "send-community (both|extended|standard)",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Send Community attribute to this neighbor\n"
+       "Send Standard and Extended Community attributes\n"
+       "Send Extended Community attributes\n"
+       "Send Standard Community attributes\n")
+{
+  if (strncmp (argv[1], "s", 1) == 0)
+    return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
+				 bgp_node_safi (vty),
+				 PEER_FLAG_SEND_COMMUNITY);
+  if (strncmp (argv[1], "e", 1) == 0)
+    return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
+				 bgp_node_safi (vty),
+				 PEER_FLAG_SEND_EXT_COMMUNITY);
+
+  return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
+			       bgp_node_safi (vty),
+			       (PEER_FLAG_SEND_COMMUNITY|
+				PEER_FLAG_SEND_EXT_COMMUNITY));
+}
+
+DEFUN (no_neighbor_send_community_type,
+       no_neighbor_send_community_type_cmd,
+       NO_NEIGHBOR_CMD2 "send-community (both|extended|standard)",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Send Community attribute to this neighbor\n"
+       "Send Standard and Extended Community attributes\n"
+       "Send Extended Community attributes\n"
+       "Send Standard Community attributes\n")
+{
+  if (strncmp (argv[1], "s", 1) == 0)
+    return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
+				   bgp_node_safi (vty),
+				   PEER_FLAG_SEND_COMMUNITY);
+  if (strncmp (argv[1], "e", 1) == 0)
+    return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
+				   bgp_node_safi (vty),
+				   PEER_FLAG_SEND_EXT_COMMUNITY);
+
+  return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
+				 bgp_node_safi (vty),
+				 (PEER_FLAG_SEND_COMMUNITY |
+				  PEER_FLAG_SEND_EXT_COMMUNITY));
+}
+
+/* neighbor soft-reconfig. */
+DEFUN (neighbor_soft_reconfiguration,
+       neighbor_soft_reconfiguration_cmd,
+       NEIGHBOR_CMD2 "soft-reconfiguration inbound",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Per neighbor soft reconfiguration\n"
+       "Allow inbound soft reconfiguration for this neighbor\n")
+{
+  return peer_af_flag_set_vty (vty, argv[0],
+			       bgp_node_afi (vty), bgp_node_safi (vty),
+			       PEER_FLAG_SOFT_RECONFIG);
+}
+
+DEFUN (no_neighbor_soft_reconfiguration,
+       no_neighbor_soft_reconfiguration_cmd,
+       NO_NEIGHBOR_CMD2 "soft-reconfiguration inbound",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Per neighbor soft reconfiguration\n"
+       "Allow inbound soft reconfiguration for this neighbor\n")
+{
+  return peer_af_flag_unset_vty (vty, argv[0],
+				 bgp_node_afi (vty), bgp_node_safi (vty),
+				 PEER_FLAG_SOFT_RECONFIG);
+}
+
+DEFUN (neighbor_route_reflector_client,
+       neighbor_route_reflector_client_cmd,
+       NEIGHBOR_CMD2 "route-reflector-client",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Configure a neighbor as Route Reflector client\n")
+{
+  struct peer *peer;
+
+
+  peer = peer_and_group_lookup_vty (vty, argv[0]);
+  if (! peer)
+    return CMD_WARNING;
+
+  return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
+			       bgp_node_safi (vty),
+			       PEER_FLAG_REFLECTOR_CLIENT);
+}
+
+DEFUN (no_neighbor_route_reflector_client,
+       no_neighbor_route_reflector_client_cmd,
+       NO_NEIGHBOR_CMD2 "route-reflector-client",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Configure a neighbor as Route Reflector client\n")
+{
+  return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
+				 bgp_node_safi (vty),
+				 PEER_FLAG_REFLECTOR_CLIENT);
+}
+
+/* neighbor route-server-client. */
+DEFUN (neighbor_route_server_client,
+       neighbor_route_server_client_cmd,
+       NEIGHBOR_CMD2 "route-server-client",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Configure a neighbor as Route Server client\n")
+{
+  return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
+			       bgp_node_safi (vty),
+			       PEER_FLAG_RSERVER_CLIENT);
+}
+
+DEFUN (no_neighbor_route_server_client,
+       no_neighbor_route_server_client_cmd,
+       NO_NEIGHBOR_CMD2 "route-server-client",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Configure a neighbor as Route Server client\n")
+{
+  return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
+				 bgp_node_safi (vty),
+				 PEER_FLAG_RSERVER_CLIENT);
+}
+
+DEFUN (neighbor_attr_unchanged,
+       neighbor_attr_unchanged_cmd,
+       NEIGHBOR_CMD2 "attribute-unchanged",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP attribute is propagated unchanged to this neighbor\n")
+{
+  return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
+			       bgp_node_safi (vty),
+			       (PEER_FLAG_AS_PATH_UNCHANGED |
+				PEER_FLAG_NEXTHOP_UNCHANGED |
+				PEER_FLAG_MED_UNCHANGED));
+}
+
+DEFUN (neighbor_attr_unchanged1,
+       neighbor_attr_unchanged1_cmd,
+       NEIGHBOR_CMD2 "attribute-unchanged (as-path|next-hop|med)",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP attribute is propagated unchanged to this neighbor\n"
+       "As-path attribute\n"
+       "Nexthop attribute\n"
+       "Med attribute\n")
+{
+  u_int16_t flags = 0;
+
+  if (strncmp (argv[1], "as-path", 1) == 0)
+    SET_FLAG (flags, PEER_FLAG_AS_PATH_UNCHANGED);
+  else if (strncmp (argv[1], "next-hop", 1) == 0)
+    SET_FLAG (flags, PEER_FLAG_NEXTHOP_UNCHANGED);
+  else if (strncmp (argv[1], "med", 1) == 0)
+    SET_FLAG (flags, PEER_FLAG_MED_UNCHANGED);
+
+  return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
+			       bgp_node_safi (vty), flags);
+}
+
+DEFUN (neighbor_attr_unchanged2,
+       neighbor_attr_unchanged2_cmd,
+       NEIGHBOR_CMD2 "attribute-unchanged as-path (next-hop|med)",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP attribute is propagated unchanged to this neighbor\n"
+       "As-path attribute\n"
+       "Nexthop attribute\n"
+       "Med attribute\n")
+{
+  u_int16_t flags = PEER_FLAG_AS_PATH_UNCHANGED;
+
+  if (strncmp (argv[1], "next-hop", 1) == 0)
+    SET_FLAG (flags, PEER_FLAG_NEXTHOP_UNCHANGED);
+  else if (strncmp (argv[1], "med", 1) == 0)
+    SET_FLAG (flags, PEER_FLAG_MED_UNCHANGED);
+
+  return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
+			       bgp_node_safi (vty), flags);
+
+}
+
+DEFUN (neighbor_attr_unchanged3,
+       neighbor_attr_unchanged3_cmd,
+       NEIGHBOR_CMD2 "attribute-unchanged next-hop (as-path|med)",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP attribute is propagated unchanged to this neighbor\n"
+       "Nexthop attribute\n"
+       "As-path attribute\n"
+       "Med attribute\n")
+{
+  u_int16_t flags = PEER_FLAG_NEXTHOP_UNCHANGED;
+
+  if (strncmp (argv[1], "as-path", 1) == 0)
+    SET_FLAG (flags, PEER_FLAG_AS_PATH_UNCHANGED);
+  else if (strncmp (argv[1], "med", 1) == 0)
+    SET_FLAG (flags, PEER_FLAG_MED_UNCHANGED);
+
+  return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
+			       bgp_node_safi (vty), flags);
+}
+
+DEFUN (neighbor_attr_unchanged4,
+       neighbor_attr_unchanged4_cmd,
+       NEIGHBOR_CMD2 "attribute-unchanged med (as-path|next-hop)",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP attribute is propagated unchanged to this neighbor\n"
+       "Med attribute\n"
+       "As-path attribute\n"
+       "Nexthop attribute\n")
+{
+  u_int16_t flags = PEER_FLAG_MED_UNCHANGED;
+
+  if (strncmp (argv[1], "as-path", 1) == 0)
+    SET_FLAG (flags, PEER_FLAG_AS_PATH_UNCHANGED);
+  else if (strncmp (argv[1], "next-hop", 1) == 0)
+    SET_FLAG (flags, PEER_FLAG_NEXTHOP_UNCHANGED);
+
+  return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
+			       bgp_node_safi (vty), flags);
+}
+
+ALIAS (neighbor_attr_unchanged,
+       neighbor_attr_unchanged5_cmd,
+       NEIGHBOR_CMD2 "attribute-unchanged as-path next-hop med",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP attribute is propagated unchanged to this neighbor\n"
+       "As-path attribute\n"
+       "Nexthop attribute\n"
+       "Med attribute\n")
+
+ALIAS (neighbor_attr_unchanged,
+       neighbor_attr_unchanged6_cmd,
+       NEIGHBOR_CMD2 "attribute-unchanged as-path med next-hop",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP attribute is propagated unchanged to this neighbor\n"
+       "As-path attribute\n"
+       "Med attribute\n"
+       "Nexthop attribute\n")
+
+ALIAS (neighbor_attr_unchanged,
+       neighbor_attr_unchanged7_cmd,
+       NEIGHBOR_CMD2 "attribute-unchanged next-hop med as-path",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP attribute is propagated unchanged to this neighbor\n"
+       "Nexthop attribute\n"
+       "Med attribute\n"
+       "As-path attribute\n")
+
+ALIAS (neighbor_attr_unchanged,
+       neighbor_attr_unchanged8_cmd,
+       NEIGHBOR_CMD2 "attribute-unchanged next-hop as-path med",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP attribute is propagated unchanged to this neighbor\n"
+       "Nexthop attribute\n"
+       "As-path attribute\n"
+       "Med attribute\n")
+
+ALIAS (neighbor_attr_unchanged,
+       neighbor_attr_unchanged9_cmd,
+       NEIGHBOR_CMD2 "attribute-unchanged med next-hop as-path",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP attribute is propagated unchanged to this neighbor\n"
+       "Med attribute\n"
+       "Nexthop attribute\n"
+       "As-path attribute\n")
+
+ALIAS (neighbor_attr_unchanged,
+       neighbor_attr_unchanged10_cmd,
+       NEIGHBOR_CMD2 "attribute-unchanged med as-path next-hop",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP attribute is propagated unchanged to this neighbor\n"
+       "Med attribute\n"
+       "As-path attribute\n"
+       "Nexthop attribute\n")
+
+DEFUN (no_neighbor_attr_unchanged,
+       no_neighbor_attr_unchanged_cmd,
+       NO_NEIGHBOR_CMD2 "attribute-unchanged",
+       NO_STR	 
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP attribute is propagated unchanged to this neighbor\n")
+{
+  return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
+				 bgp_node_safi (vty),
+				 (PEER_FLAG_AS_PATH_UNCHANGED |
+				  PEER_FLAG_NEXTHOP_UNCHANGED |
+				  PEER_FLAG_MED_UNCHANGED));
+}
+
+DEFUN (no_neighbor_attr_unchanged1,
+       no_neighbor_attr_unchanged1_cmd,
+       NO_NEIGHBOR_CMD2 "attribute-unchanged (as-path|next-hop|med)",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP attribute is propagated unchanged to this neighbor\n"
+       "As-path attribute\n"
+       "Nexthop attribute\n"
+       "Med attribute\n")
+{
+  u_int16_t flags = 0;
+
+  if (strncmp (argv[1], "as-path", 1) == 0)
+    SET_FLAG (flags, PEER_FLAG_AS_PATH_UNCHANGED);
+  else if (strncmp (argv[1], "next-hop", 1) == 0)
+    SET_FLAG (flags, PEER_FLAG_NEXTHOP_UNCHANGED);
+  else if (strncmp (argv[1], "med", 1) == 0)
+    SET_FLAG (flags, PEER_FLAG_MED_UNCHANGED);
+
+  return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
+				 bgp_node_safi (vty), flags);
+}
+
+DEFUN (no_neighbor_attr_unchanged2,
+       no_neighbor_attr_unchanged2_cmd,
+       NO_NEIGHBOR_CMD2 "attribute-unchanged as-path (next-hop|med)",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP attribute is propagated unchanged to this neighbor\n"
+       "As-path attribute\n"
+       "Nexthop attribute\n"
+       "Med attribute\n")
+{
+  u_int16_t flags = PEER_FLAG_AS_PATH_UNCHANGED;
+
+  if (strncmp (argv[1], "next-hop", 1) == 0)
+    SET_FLAG (flags, PEER_FLAG_NEXTHOP_UNCHANGED);
+  else if (strncmp (argv[1], "med", 1) == 0)
+    SET_FLAG (flags, PEER_FLAG_MED_UNCHANGED);
+
+  return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
+			       bgp_node_safi (vty), flags);
+}
+
+DEFUN (no_neighbor_attr_unchanged3,
+       no_neighbor_attr_unchanged3_cmd,
+       NO_NEIGHBOR_CMD2 "attribute-unchanged next-hop (as-path|med)",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP attribute is propagated unchanged to this neighbor\n"
+       "Nexthop attribute\n"
+       "As-path attribute\n"
+       "Med attribute\n")
+{
+  u_int16_t flags = PEER_FLAG_NEXTHOP_UNCHANGED;
+
+  if (strncmp (argv[1], "as-path", 1) == 0)
+    SET_FLAG (flags, PEER_FLAG_AS_PATH_UNCHANGED);
+  else if (strncmp (argv[1], "med", 1) == 0)
+    SET_FLAG (flags, PEER_FLAG_MED_UNCHANGED);
+
+  return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
+				 bgp_node_safi (vty), flags);
+}
+
+DEFUN (no_neighbor_attr_unchanged4,
+       no_neighbor_attr_unchanged4_cmd,
+       NO_NEIGHBOR_CMD2 "attribute-unchanged med (as-path|next-hop)",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP attribute is propagated unchanged to this neighbor\n"
+       "Med attribute\n"
+       "As-path attribute\n"
+       "Nexthop attribute\n")
+{
+  u_int16_t flags = PEER_FLAG_MED_UNCHANGED;
+
+  if (strncmp (argv[1], "as-path", 1) == 0)
+    SET_FLAG (flags, PEER_FLAG_AS_PATH_UNCHANGED);
+  else if (strncmp (argv[1], "next-hop", 1) == 0)
+    SET_FLAG (flags, PEER_FLAG_NEXTHOP_UNCHANGED);
+
+  return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty),
+			       bgp_node_safi (vty), flags);
+}
+
+ALIAS (no_neighbor_attr_unchanged,
+       no_neighbor_attr_unchanged5_cmd,
+       NO_NEIGHBOR_CMD2 "attribute-unchanged as-path next-hop med",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP attribute is propagated unchanged to this neighbor\n"
+       "As-path attribute\n"
+       "Nexthop attribute\n"
+       "Med attribute\n")
+
+ALIAS (no_neighbor_attr_unchanged,
+       no_neighbor_attr_unchanged6_cmd,
+       NO_NEIGHBOR_CMD2 "attribute-unchanged as-path med next-hop",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP attribute is propagated unchanged to this neighbor\n"
+       "As-path attribute\n"
+       "Med attribute\n"
+       "Nexthop attribute\n")
+
+ALIAS (no_neighbor_attr_unchanged,
+       no_neighbor_attr_unchanged7_cmd,
+       NO_NEIGHBOR_CMD2 "attribute-unchanged next-hop med as-path",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP attribute is propagated unchanged to this neighbor\n"
+       "Nexthop attribute\n"
+       "Med attribute\n"
+       "As-path attribute\n")
+
+ALIAS (no_neighbor_attr_unchanged,
+       no_neighbor_attr_unchanged8_cmd,
+       NO_NEIGHBOR_CMD2 "attribute-unchanged next-hop as-path med",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP attribute is propagated unchanged to this neighbor\n"
+       "Nexthop attribute\n"
+       "As-path attribute\n"
+       "Med attribute\n")
+
+ALIAS (no_neighbor_attr_unchanged,
+       no_neighbor_attr_unchanged9_cmd,
+       NO_NEIGHBOR_CMD2 "attribute-unchanged med next-hop as-path",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP attribute is propagated unchanged to this neighbor\n"
+       "Med attribute\n"
+       "Nexthop attribute\n"
+       "As-path attribute\n")
+
+ALIAS (no_neighbor_attr_unchanged,
+       no_neighbor_attr_unchanged10_cmd,
+       NO_NEIGHBOR_CMD2 "attribute-unchanged med as-path next-hop",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP attribute is propagated unchanged to this neighbor\n"
+       "Med attribute\n"
+       "As-path attribute\n"
+       "Nexthop attribute\n")
+
+/* For old version Zebra compatibility.  */
+DEFUN (neighbor_transparent_as,
+       neighbor_transparent_as_cmd,
+       NEIGHBOR_CMD "transparent-as",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR
+       "Do not append my AS number even peer is EBGP peer\n")
+{
+  return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
+			       bgp_node_safi (vty),
+			       PEER_FLAG_AS_PATH_UNCHANGED);
+}
+
+DEFUN (neighbor_transparent_nexthop,
+       neighbor_transparent_nexthop_cmd,
+       NEIGHBOR_CMD "transparent-nexthop",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR
+       "Do not change nexthop even peer is EBGP peer\n")
+{
+  return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty),
+			       bgp_node_safi (vty),
+			       PEER_FLAG_NEXTHOP_UNCHANGED);
+}
+
+/* EBGP multihop configuration. */
+int
+peer_ebgp_multihop_set_vty (struct vty *vty, char *ip_str, char *ttl_str)
+{
+  struct peer *peer;
+  int ttl;
+
+  peer = peer_and_group_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  if (! ttl_str)
+    ttl = TTL_MAX;
+  else
+    VTY_GET_INTEGER_RANGE ("TTL", ttl, ttl_str, 1, 255);
+
+  peer_ebgp_multihop_set (peer, ttl);
+
+  return CMD_SUCCESS;
+}
+
+int
+peer_ebgp_multihop_unset_vty (struct vty *vty, char *ip_str) 
+{
+  struct peer *peer;
+
+  peer = peer_and_group_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  peer_ebgp_multihop_unset (peer);
+
+  return CMD_SUCCESS;
+}
+
+/* neighbor ebgp-multihop. */
+DEFUN (neighbor_ebgp_multihop,
+       neighbor_ebgp_multihop_cmd,
+       NEIGHBOR_CMD2 "ebgp-multihop",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Allow EBGP neighbors not on directly connected networks\n")
+{
+  return peer_ebgp_multihop_set_vty (vty, argv[0], NULL);
+}
+
+DEFUN (neighbor_ebgp_multihop_ttl,
+       neighbor_ebgp_multihop_ttl_cmd,
+       NEIGHBOR_CMD2 "ebgp-multihop <1-255>",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Allow EBGP neighbors not on directly connected networks\n"
+       "maximum hop count\n")
+{
+  return peer_ebgp_multihop_set_vty (vty, argv[0], argv[1]);
+}
+
+DEFUN (no_neighbor_ebgp_multihop,
+       no_neighbor_ebgp_multihop_cmd,
+       NO_NEIGHBOR_CMD2 "ebgp-multihop",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Allow EBGP neighbors not on directly connected networks\n")
+{
+  return peer_ebgp_multihop_unset_vty (vty, argv[0]);
+}
+
+ALIAS (no_neighbor_ebgp_multihop,
+       no_neighbor_ebgp_multihop_ttl_cmd,
+       NO_NEIGHBOR_CMD2 "ebgp-multihop <1-255>",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Allow EBGP neighbors not on directly connected networks\n"
+       "maximum hop count\n")
+
+/* Enforce multihop.  */
+DEFUN (neighbor_enforce_multihop,
+       neighbor_enforce_multihop_cmd,
+       NEIGHBOR_CMD2 "enforce-multihop",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Enforce EBGP neighbors perform multihop\n")
+{
+  return peer_flag_set_vty (vty, argv[0], PEER_FLAG_ENFORCE_MULTIHOP);
+}
+
+DEFUN (no_neighbor_enforce_multihop,
+       no_neighbor_enforce_multihop_cmd,
+       NO_NEIGHBOR_CMD2 "enforce-multihop",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Enforce EBGP neighbors perform multihop\n")
+{
+  return peer_flag_unset_vty (vty, argv[0], PEER_FLAG_ENFORCE_MULTIHOP);
+}
+
+DEFUN (neighbor_description,
+       neighbor_description_cmd,
+       NEIGHBOR_CMD2 "description .LINE",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Neighbor specific description\n"
+       "Up to 80 characters describing this neighbor\n")
+{
+  struct peer *peer;
+  struct buffer *b;
+  char *str;
+  int i;
+
+  peer = peer_and_group_lookup_vty (vty, argv[0]);
+  if (! peer)
+    return CMD_WARNING;
+
+  if (argc == 1)
+    return CMD_SUCCESS;
+
+  /* Make string from buffer.  This function should be provided by
+     buffer.c. */
+  b = buffer_new (1024);
+  for (i = 1; i < argc; i++)
+    {
+      buffer_putstr (b, (u_char *)argv[i]);
+      buffer_putc (b, ' ');
+    }
+  buffer_putc (b, '\0');
+  str = buffer_getstr (b);
+  buffer_free (b);
+
+  peer_description_set (peer, str);
+
+  free (str);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_neighbor_description,
+       no_neighbor_description_cmd,
+       NO_NEIGHBOR_CMD2 "description",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Neighbor specific description\n")
+{
+  struct peer *peer;
+
+  peer = peer_and_group_lookup_vty (vty, argv[0]);
+  if (! peer)
+    return CMD_WARNING;
+
+  peer_description_unset (peer);
+
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_neighbor_description,
+       no_neighbor_description_val_cmd,
+       NO_NEIGHBOR_CMD2 "description .LINE",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Neighbor specific description\n"
+       "Up to 80 characters describing this neighbor\n")
+
+/* Neighbor update-source. */
+int
+peer_update_source_vty (struct vty *vty, char *peer_str, char *source_str)
+{
+  struct peer *peer;
+  union sockunion *su;
+
+  peer = peer_and_group_lookup_vty (vty, peer_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  if (source_str)
+    {
+      su = sockunion_str2su (source_str);
+      if (su)
+	{
+	  peer_update_source_addr_set (peer, su);
+	  sockunion_free (su);
+	}
+      else
+	peer_update_source_if_set (peer, source_str);
+    }
+  else
+    peer_update_source_unset (peer);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (neighbor_update_source,
+       neighbor_update_source_cmd,
+       NEIGHBOR_CMD2 "update-source WORD",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Source of routing updates\n"
+       "Interface name\n")
+{
+  return peer_update_source_vty (vty, argv[0], argv[1]);
+}
+
+DEFUN (no_neighbor_update_source,
+       no_neighbor_update_source_cmd,
+       NO_NEIGHBOR_CMD2 "update-source",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Source of routing updates\n"
+       "Interface name\n")
+{
+  return peer_update_source_vty (vty, argv[0], NULL);
+}
+
+int
+peer_default_originate_set_vty (struct vty *vty, char *peer_str, afi_t afi,
+				safi_t safi, char *rmap, int set)
+{
+  int ret;
+  struct peer *peer;
+
+  peer = peer_and_group_lookup_vty (vty, peer_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  if (set)
+    ret = peer_default_originate_set (peer, afi, safi, rmap);
+  else
+    ret = peer_default_originate_unset (peer, afi, safi);
+
+  return bgp_vty_return (vty, ret);
+}
+
+/* neighbor default-originate. */
+DEFUN (neighbor_default_originate,
+       neighbor_default_originate_cmd,
+       NEIGHBOR_CMD2 "default-originate",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Originate default route to this neighbor\n")
+{
+  return peer_default_originate_set_vty (vty, argv[0], bgp_node_afi (vty),
+					 bgp_node_safi (vty), NULL, 1);
+}
+
+DEFUN (neighbor_default_originate_rmap,
+       neighbor_default_originate_rmap_cmd,
+       NEIGHBOR_CMD2 "default-originate route-map WORD",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Originate default route to this neighbor\n"
+       "Route-map to specify criteria to originate default\n"
+       "route-map name\n")
+{
+  return peer_default_originate_set_vty (vty, argv[0], bgp_node_afi (vty),
+					 bgp_node_safi (vty), argv[1], 1);
+}
+
+DEFUN (no_neighbor_default_originate,
+       no_neighbor_default_originate_cmd,
+       NO_NEIGHBOR_CMD2 "default-originate",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Originate default route to this neighbor\n")
+{
+  return peer_default_originate_set_vty (vty, argv[0], bgp_node_afi (vty),
+					 bgp_node_safi (vty), NULL, 0);
+}
+
+ALIAS (no_neighbor_default_originate,
+       no_neighbor_default_originate_rmap_cmd,
+       NO_NEIGHBOR_CMD2 "default-originate route-map WORD",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Originate default route to this neighbor\n"
+       "Route-map to specify criteria to originate default\n"
+       "route-map name\n")
+
+/* Set neighbor's BGP port.  */
+int
+peer_port_vty (struct vty *vty, char *ip_str, int afi, char *port_str)
+{
+  struct peer *peer;
+  u_int16_t port;
+  struct servent *sp;
+
+  peer = peer_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  if (! port_str)
+    { 
+      sp = getservbyname ("bgp", "tcp");
+      port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
+    }
+  else
+    {
+      VTY_GET_INTEGER("port", port, port_str);
+    }
+
+  peer_port_set (peer, port);
+
+  return CMD_SUCCESS;
+}
+
+/* Set specified peer's BGP version.  */
+DEFUN (neighbor_port,
+       neighbor_port_cmd,
+       NEIGHBOR_CMD "port <0-65535>",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR
+       "Neighbor's BGP port\n"
+       "TCP port number\n")
+{
+  return peer_port_vty (vty, argv[0], AFI_IP, argv[1]);
+}
+
+DEFUN (no_neighbor_port,
+       no_neighbor_port_cmd,
+       NO_NEIGHBOR_CMD "port",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR
+       "Neighbor's BGP port\n")
+{
+  return peer_port_vty (vty, argv[0], AFI_IP, NULL);
+}
+
+ALIAS (no_neighbor_port,
+       no_neighbor_port_val_cmd,
+       NO_NEIGHBOR_CMD "port <0-65535>",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR
+       "Neighbor's BGP port\n"
+       "TCP port number\n")
+
+/* neighbor weight. */
+int
+peer_weight_set_vty (struct vty *vty, char *ip_str, char *weight_str)
+{
+  int ret;
+  struct peer *peer;
+  unsigned long weight;
+
+  peer = peer_and_group_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  VTY_GET_INTEGER_RANGE("weight", weight, weight_str, 0, 65535);
+
+  ret = peer_weight_set (peer, weight);
+
+  return CMD_SUCCESS;
+}
+
+int
+peer_weight_unset_vty (struct vty *vty, char *ip_str)
+{
+  struct peer *peer;
+
+  peer = peer_and_group_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  peer_weight_unset (peer);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (neighbor_weight,
+       neighbor_weight_cmd,
+       NEIGHBOR_CMD2 "weight <0-65535>",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Set default weight for routes from this neighbor\n"
+       "default weight\n")
+{
+  return peer_weight_set_vty (vty, argv[0], argv[1]);
+}
+
+DEFUN (no_neighbor_weight,
+       no_neighbor_weight_cmd,
+       NO_NEIGHBOR_CMD2 "weight",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Set default weight for routes from this neighbor\n")
+{
+  return peer_weight_unset_vty (vty, argv[0]);
+}
+
+ALIAS (no_neighbor_weight,
+       no_neighbor_weight_val_cmd,
+       NO_NEIGHBOR_CMD2 "weight <0-65535>",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Set default weight for routes from this neighbor\n"
+       "default weight\n")
+
+/* Override capability negotiation. */
+DEFUN (neighbor_override_capability,
+       neighbor_override_capability_cmd,
+       NEIGHBOR_CMD2 "override-capability",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Override capability negotiation result\n")
+{
+  return peer_flag_set_vty (vty, argv[0], PEER_FLAG_OVERRIDE_CAPABILITY);
+}
+
+DEFUN (no_neighbor_override_capability,
+       no_neighbor_override_capability_cmd,
+       NO_NEIGHBOR_CMD2 "override-capability",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Override capability negotiation result\n")
+{
+  return peer_flag_unset_vty (vty, argv[0], PEER_FLAG_OVERRIDE_CAPABILITY);
+}
+
+DEFUN (neighbor_strict_capability,
+       neighbor_strict_capability_cmd,
+       NEIGHBOR_CMD "strict-capability-match",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR
+       "Strict capability negotiation match\n")
+{
+  return peer_flag_set_vty (vty, argv[0], PEER_FLAG_STRICT_CAP_MATCH);
+}
+
+DEFUN (no_neighbor_strict_capability,
+       no_neighbor_strict_capability_cmd,
+       NO_NEIGHBOR_CMD "strict-capability-match",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR
+       "Strict capability negotiation match\n")
+{
+  return peer_flag_unset_vty (vty, argv[0], PEER_FLAG_STRICT_CAP_MATCH);
+}
+
+int
+peer_timers_set_vty (struct vty *vty, char *ip_str, char *keep_str,
+		     char *hold_str)
+{
+  int ret;
+  struct peer *peer;
+  u_int32_t keepalive;
+  u_int32_t holdtime;
+
+  peer = peer_and_group_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  VTY_GET_INTEGER_RANGE ("Keepalive", keepalive, keep_str, 0, 65535);
+  VTY_GET_INTEGER_RANGE ("Holdtime", holdtime, hold_str, 0, 65535);
+
+  ret = peer_timers_set (peer, keepalive, holdtime);
+
+  return bgp_vty_return (vty, ret);
+}
+
+int
+peer_timers_unset_vty (struct vty *vty, char *ip_str)
+{
+  int ret;
+  struct peer *peer;
+
+  peer = peer_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  ret = peer_timers_unset (peer);
+
+  return bgp_vty_return (vty, ret);
+}
+
+DEFUN (neighbor_timers,
+       neighbor_timers_cmd,
+       NEIGHBOR_CMD2 "timers <0-65535> <0-65535>",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP per neighbor timers\n"
+       "Keepalive interval\n"
+       "Holdtime\n")
+{
+  return peer_timers_set_vty (vty, argv[0], argv[1], argv[2]);
+}
+
+DEFUN (no_neighbor_timers,
+       no_neighbor_timers_cmd,
+       NO_NEIGHBOR_CMD2 "timers",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "BGP per neighbor timers\n")
+{
+  return peer_timers_unset_vty (vty, argv[0]);
+}
+
+int
+peer_timers_connect_set_vty (struct vty *vty, char *ip_str, char *time_str)
+{
+  int ret;
+  struct peer *peer;
+  u_int32_t connect;
+
+  peer = peer_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  VTY_GET_INTEGER_RANGE ("Connect time", connect, time_str, 0, 65535);
+
+  ret = peer_timers_connect_set (peer, connect);
+
+  return CMD_SUCCESS;
+}
+
+int
+peer_timers_connect_unset_vty (struct vty *vty, char *ip_str)
+{
+  int ret;
+  struct peer *peer;
+
+  peer = peer_and_group_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  ret = peer_timers_connect_unset (peer);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (neighbor_timers_connect,
+       neighbor_timers_connect_cmd,
+       NEIGHBOR_CMD "timers connect <0-65535>",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR
+       "BGP per neighbor timers\n"
+       "BGP connect timer\n"
+       "Connect timer\n")
+{
+  return peer_timers_connect_set_vty (vty, argv[0], argv[1]);
+}
+
+DEFUN (no_neighbor_timers_connect,
+       no_neighbor_timers_connect_cmd,
+       NO_NEIGHBOR_CMD "timers connect",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR
+       "BGP per neighbor timers\n"
+       "BGP connect timer\n")
+{
+  return peer_timers_connect_unset_vty (vty, argv[0]);
+}
+
+ALIAS (no_neighbor_timers_connect,
+       no_neighbor_timers_connect_val_cmd,
+       NO_NEIGHBOR_CMD "timers connect <0-65535>",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR
+       "BGP per neighbor timers\n"
+       "BGP connect timer\n"
+       "Connect timer\n")
+
+int
+peer_advertise_interval_vty (struct vty *vty, char *ip_str, char *time_str,
+			     int set)  
+{
+  int ret;
+  struct peer *peer;
+  u_int32_t routeadv = 0;
+
+  peer = peer_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  if (time_str)
+    VTY_GET_INTEGER_RANGE ("advertise interval", routeadv, time_str, 0, 600);
+
+  if (set)
+    ret = peer_advertise_interval_set (peer, routeadv);
+  else
+    ret = peer_advertise_interval_unset (peer);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (neighbor_advertise_interval,
+       neighbor_advertise_interval_cmd,
+       NEIGHBOR_CMD "advertisement-interval <0-600>",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR
+       "Minimum interval between sending BGP routing updates\n"
+       "time in seconds\n")
+{
+  return peer_advertise_interval_vty (vty, argv[0], argv[1], 1);
+}
+
+DEFUN (no_neighbor_advertise_interval,
+       no_neighbor_advertise_interval_cmd,
+       NO_NEIGHBOR_CMD "advertisement-interval",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR
+       "Minimum interval between sending BGP routing updates\n")
+{
+  return peer_advertise_interval_vty (vty, argv[0], NULL, 0);
+}
+
+ALIAS (no_neighbor_advertise_interval,
+       no_neighbor_advertise_interval_val_cmd,
+       NO_NEIGHBOR_CMD "advertisement-interval <0-600>",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR
+       "Minimum interval between sending BGP routing updates\n"
+       "time in seconds\n")
+
+int
+peer_version_vty (struct vty *vty, char *ip_str, char *str)
+{
+  int ret;
+  struct peer *peer;
+  int version = BGP_VERSION_4;
+
+  peer = peer_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  /* BGP version string check. */
+  if (str)
+    {
+      if (strcmp (str, "4") == 0)
+	version = BGP_VERSION_4;
+      else if (strcmp (str, "4-") == 0)
+	version = BGP_VERSION_MP_4_DRAFT_00;
+
+      ret = peer_version_set (peer, version);
+    }
+  else
+    ret = peer_version_unset (peer);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (neighbor_version,
+       neighbor_version_cmd,
+       NEIGHBOR_CMD "version (4|4-)",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR
+       "Neighbor's BGP version\n"
+       "Border Gateway Protocol 4\n"
+       "Multiprotocol Extensions for BGP-4(Old Draft)\n")
+{
+  return peer_version_vty (vty, argv[0], argv[1]);
+}
+
+DEFUN (no_neighbor_version,
+       no_neighbor_version_cmd,
+       NO_NEIGHBOR_CMD "version",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR
+       "Neighbor's BGP version\n")
+{
+  return peer_version_vty (vty, argv[0], NULL);
+}
+
+/* neighbor interface */
+int
+peer_interface_vty (struct vty *vty, char *ip_str, char *str)
+{
+  int ret;
+  struct peer *peer;
+
+  peer = peer_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  if (str)
+    ret = peer_interface_set (peer, str);
+  else
+    ret = peer_interface_unset (peer);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (neighbor_interface,
+       neighbor_interface_cmd,
+       NEIGHBOR_CMD "interface WORD",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR
+       "Interface\n"
+       "Interface name\n")
+{
+  return peer_interface_vty (vty, argv[0], argv[1]);
+}
+
+DEFUN (no_neighbor_interface,
+       no_neighbor_interface_cmd,
+       NO_NEIGHBOR_CMD "interface WORD",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR
+       "Interface\n"
+       "Interface name\n")
+{
+  return peer_interface_vty (vty, argv[0], NULL);
+}
+
+/* Set distribute list to the peer. */
+int
+peer_distribute_set_vty (struct vty *vty, char *ip_str, afi_t afi, safi_t safi,
+			 char *name_str, char *direct_str)
+{
+  int ret;
+  struct peer *peer;
+  int direct = FILTER_IN;
+
+  peer = peer_and_group_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  /* Check filter direction. */
+  if (strncmp (direct_str, "i", 1) == 0)
+    direct = FILTER_IN;
+  else if (strncmp (direct_str, "o", 1) == 0)
+    direct = FILTER_OUT;
+
+  ret = peer_distribute_set (peer, afi, safi, direct, name_str);
+
+  return bgp_vty_return (vty, ret);
+}
+
+int
+peer_distribute_unset_vty (struct vty *vty, char *ip_str, afi_t afi,
+			   safi_t safi, char *direct_str)
+{
+  int ret;
+  struct peer *peer;
+  int direct = FILTER_IN;
+
+  peer = peer_and_group_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  /* Check filter direction. */
+  if (strncmp (direct_str, "i", 1) == 0)
+    direct = FILTER_IN;
+  else if (strncmp (direct_str, "o", 1) == 0)
+    direct = FILTER_OUT;
+
+  ret = peer_distribute_unset (peer, afi, safi, direct);
+
+  return bgp_vty_return (vty, ret);
+}
+
+DEFUN (neighbor_distribute_list,
+       neighbor_distribute_list_cmd,
+       NEIGHBOR_CMD2 "distribute-list (<1-199>|<1300-2699>|WORD) (in|out)",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Filter updates to/from this neighbor\n"
+       "IP access-list number\n"
+       "IP access-list number (expanded range)\n"
+       "IP Access-list name\n"
+       "Filter incoming updates\n"
+       "Filter outgoing updates\n")
+{
+  return peer_distribute_set_vty (vty, argv[0], bgp_node_afi (vty),
+				  bgp_node_safi (vty), argv[1], argv[2]);
+}
+
+DEFUN (no_neighbor_distribute_list,
+       no_neighbor_distribute_list_cmd,
+       NO_NEIGHBOR_CMD2 "distribute-list (<1-199>|<1300-2699>|WORD) (in|out)",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Filter updates to/from this neighbor\n"
+       "IP access-list number\n"
+       "IP access-list number (expanded range)\n"
+       "IP Access-list name\n"
+       "Filter incoming updates\n"
+       "Filter outgoing updates\n")
+{
+  return peer_distribute_unset_vty (vty, argv[0], bgp_node_afi (vty),
+				    bgp_node_safi (vty), argv[2]);
+}
+
+/* Set prefix list to the peer. */
+int
+peer_prefix_list_set_vty (struct vty *vty, char *ip_str, afi_t afi,
+			  safi_t safi, char *name_str, char *direct_str)
+{
+  int ret;
+  struct peer *peer;
+  int direct = FILTER_IN;
+
+  peer = peer_and_group_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  /* Check filter direction. */
+  if (strncmp (direct_str, "i", 1) == 0)
+    direct = FILTER_IN;
+  else if (strncmp (direct_str, "o", 1) == 0)
+    direct = FILTER_OUT;
+
+  ret = peer_prefix_list_set (peer, afi, safi, direct, name_str);
+
+  return bgp_vty_return (vty, ret);
+}
+
+int
+peer_prefix_list_unset_vty (struct vty *vty, char *ip_str, afi_t afi,
+			    safi_t safi, char *direct_str)
+{
+  int ret;
+  struct peer *peer;
+  int direct = FILTER_IN;
+
+  peer = peer_and_group_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+  
+  /* Check filter direction. */
+  if (strncmp (direct_str, "i", 1) == 0)
+    direct = FILTER_IN;
+  else if (strncmp (direct_str, "o", 1) == 0)
+    direct = FILTER_OUT;
+
+  ret = peer_prefix_list_unset (peer, afi, safi, direct);
+
+  return bgp_vty_return (vty, ret);
+}
+
+DEFUN (neighbor_prefix_list,
+       neighbor_prefix_list_cmd,
+       NEIGHBOR_CMD2 "prefix-list WORD (in|out)",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Filter updates to/from this neighbor\n"
+       "Name of a prefix list\n"
+       "Filter incoming updates\n"
+       "Filter outgoing updates\n")
+{
+  return peer_prefix_list_set_vty (vty, argv[0], bgp_node_afi (vty),
+				   bgp_node_safi (vty), argv[1], argv[2]);
+}
+
+DEFUN (no_neighbor_prefix_list,
+       no_neighbor_prefix_list_cmd,
+       NO_NEIGHBOR_CMD2 "prefix-list WORD (in|out)",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Filter updates to/from this neighbor\n"
+       "Name of a prefix list\n"
+       "Filter incoming updates\n"
+       "Filter outgoing updates\n")
+{
+  return peer_prefix_list_unset_vty (vty, argv[0], bgp_node_afi (vty),
+				     bgp_node_safi (vty), argv[2]);
+}
+
+int
+peer_aslist_set_vty (struct vty *vty, char *ip_str, afi_t afi, safi_t safi,
+		     char *name_str, char *direct_str)
+{
+  int ret;
+  struct peer *peer;
+  int direct = FILTER_IN;
+
+  peer = peer_and_group_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  /* Check filter direction. */
+  if (strncmp (direct_str, "i", 1) == 0)
+    direct = FILTER_IN;
+  else if (strncmp (direct_str, "o", 1) == 0)
+    direct = FILTER_OUT;
+
+  ret = peer_aslist_set (peer, afi, safi, direct, name_str);
+
+  return bgp_vty_return (vty, ret);
+}
+
+int
+peer_aslist_unset_vty (struct vty *vty, char *ip_str, afi_t afi, safi_t safi,
+		       char *direct_str)
+{
+  int ret;
+  struct peer *peer;
+  int direct = FILTER_IN;
+
+  peer = peer_and_group_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  /* Check filter direction. */
+  if (strncmp (direct_str, "i", 1) == 0)
+    direct = FILTER_IN;
+  else if (strncmp (direct_str, "o", 1) == 0)
+    direct = FILTER_OUT;
+
+  ret = peer_aslist_unset (peer, afi, safi, direct);
+
+  return bgp_vty_return (vty, ret);
+}
+
+DEFUN (neighbor_filter_list,
+       neighbor_filter_list_cmd,
+       NEIGHBOR_CMD2 "filter-list WORD (in|out)",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Establish BGP filters\n"
+       "AS path access-list name\n"
+       "Filter incoming routes\n"
+       "Filter outgoing routes\n")
+{
+  return peer_aslist_set_vty (vty, argv[0], bgp_node_afi (vty),
+			      bgp_node_safi (vty), argv[1], argv[2]);
+}
+
+DEFUN (no_neighbor_filter_list,
+       no_neighbor_filter_list_cmd,
+       NO_NEIGHBOR_CMD2 "filter-list WORD (in|out)",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Establish BGP filters\n"
+       "AS path access-list name\n"
+       "Filter incoming routes\n"
+       "Filter outgoing routes\n")
+{
+  return peer_aslist_unset_vty (vty, argv[0], bgp_node_afi (vty),
+				bgp_node_safi (vty), argv[2]);
+}
+
+/* Set route-map to the peer. */
+int
+peer_route_map_set_vty (struct vty *vty, char *ip_str, afi_t afi, safi_t safi,
+			char *name_str, char *direct_str)
+{
+  int ret;
+  struct peer *peer;
+  int direct = FILTER_IN;
+
+  peer = peer_and_group_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  /* Check filter direction. */
+  if (strncmp (direct_str, "i", 1) == 0)
+    direct = FILTER_IN;
+  else if (strncmp (direct_str, "o", 1) == 0)
+    direct = FILTER_OUT;
+
+  ret = peer_route_map_set (peer, afi, safi, direct, name_str);
+
+  return bgp_vty_return (vty, ret);
+}
+
+int
+peer_route_map_unset_vty (struct vty *vty, char *ip_str, afi_t afi,
+			  safi_t safi, char *direct_str)
+{
+  int ret;
+  struct peer *peer;
+  int direct = FILTER_IN;
+
+  peer = peer_and_group_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  /* Check filter direction. */
+  if (strncmp (direct_str, "i", 1) == 0)
+    direct = FILTER_IN;
+  else if (strncmp (direct_str, "o", 1) == 0)
+
+    direct = FILTER_OUT;
+
+  ret = peer_route_map_unset (peer, afi, safi, direct);
+
+  return bgp_vty_return (vty, ret);
+}
+
+DEFUN (neighbor_route_map,
+       neighbor_route_map_cmd,
+       NEIGHBOR_CMD2 "route-map WORD (in|out)",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Apply route map to neighbor\n"
+       "Name of route map\n"
+       "Apply map to incoming routes\n"
+       "Apply map to outbound routes\n")
+{
+  return peer_route_map_set_vty (vty, argv[0], bgp_node_afi (vty),
+				 bgp_node_safi (vty), argv[1], argv[2]);
+}
+
+DEFUN (no_neighbor_route_map,
+       no_neighbor_route_map_cmd,
+       NO_NEIGHBOR_CMD2 "route-map WORD (in|out)",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Apply route map to neighbor\n"
+       "Name of route map\n"
+       "Apply map to incoming routes\n"
+       "Apply map to outbound routes\n")
+{
+  return peer_route_map_unset_vty (vty, argv[0], bgp_node_afi (vty),
+				   bgp_node_safi (vty), argv[2]);
+}
+
+/* Set unsuppress-map to the peer. */
+int
+peer_unsuppress_map_set_vty (struct vty *vty, char *ip_str, afi_t afi,
+			     safi_t safi, char *name_str)
+{
+  int ret;
+  struct peer *peer;
+
+  peer = peer_and_group_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  ret = peer_unsuppress_map_set (peer, afi, safi, name_str);
+
+  return bgp_vty_return (vty, ret);
+}
+
+/* Unset route-map from the peer. */
+int
+peer_unsuppress_map_unset_vty (struct vty *vty, char *ip_str, afi_t afi,
+			       safi_t safi)
+{
+  int ret;
+  struct peer *peer;
+
+  peer = peer_and_group_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  ret = peer_unsuppress_map_unset (peer, afi, safi);
+
+  return bgp_vty_return (vty, ret);
+}
+
+DEFUN (neighbor_unsuppress_map,
+       neighbor_unsuppress_map_cmd,
+       NEIGHBOR_CMD2 "unsuppress-map WORD",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Route-map to selectively unsuppress suppressed routes\n"
+       "Name of route map\n")
+{
+  return peer_unsuppress_map_set_vty (vty, argv[0], bgp_node_afi (vty),
+				      bgp_node_safi (vty), argv[1]);
+}
+
+DEFUN (no_neighbor_unsuppress_map,
+       no_neighbor_unsuppress_map_cmd,
+       NO_NEIGHBOR_CMD2 "unsuppress-map WORD",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Route-map to selectively unsuppress suppressed routes\n"
+       "Name of route map\n")
+{
+  return peer_unsuppress_map_unset_vty (vty, argv[0], bgp_node_afi (vty),
+					bgp_node_safi (vty));
+}
+
+int
+peer_maximum_prefix_set_vty (struct vty *vty, char *ip_str, afi_t afi,
+			     safi_t safi, char *num_str, int warning)
+{
+  int ret;
+  struct peer *peer;
+  u_int32_t max;
+
+  peer = peer_and_group_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  VTY_GET_INTEGER ("maxmum number", max, num_str);
+
+  ret = peer_maximum_prefix_set (peer, afi, safi, max, warning);
+
+  return bgp_vty_return (vty, ret);
+}
+
+int
+peer_maximum_prefix_unset_vty (struct vty *vty, char *ip_str, afi_t afi,
+			       safi_t safi)
+{
+  int ret;
+  struct peer *peer;
+
+  peer = peer_and_group_lookup_vty (vty, ip_str);
+  if (! peer)
+    return CMD_WARNING;
+
+  ret = peer_maximum_prefix_unset (peer, afi, safi);
+
+  return bgp_vty_return (vty, ret);
+}
+
+/* Maximum number of prefix configuration.  prefix count is different
+   for each peer configuration.  So this configuration can be set for
+   each peer configuration. */
+DEFUN (neighbor_maximum_prefix,
+       neighbor_maximum_prefix_cmd,
+       NEIGHBOR_CMD2 "maximum-prefix <1-4294967295>",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Maximum number of prefix accept from this peer\n"
+       "maximum no. of prefix limit\n")
+{
+  return peer_maximum_prefix_set_vty (vty, argv[0], bgp_node_afi (vty),
+				      bgp_node_safi (vty), argv[1], 0);
+}
+
+DEFUN (neighbor_maximum_prefix_warning,
+       neighbor_maximum_prefix_warning_cmd,
+       NEIGHBOR_CMD2 "maximum-prefix <1-4294967295> warning-only",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Maximum number of prefix accept from this peer\n"
+       "maximum no. of prefix limit\n"
+       "Only give warning message when limit is exceeded\n")
+{
+  return peer_maximum_prefix_set_vty (vty, argv[0], bgp_node_afi (vty),
+				      bgp_node_safi (vty), argv[1], 1);
+}
+
+DEFUN (no_neighbor_maximum_prefix,
+       no_neighbor_maximum_prefix_cmd,
+       NO_NEIGHBOR_CMD2 "maximum-prefix",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Maximum number of prefix accept from this peer\n")
+{
+  return peer_maximum_prefix_unset_vty (vty, argv[0], bgp_node_afi (vty),
+					bgp_node_safi (vty));
+}
+ 
+ALIAS (no_neighbor_maximum_prefix,
+       no_neighbor_maximum_prefix_val_cmd,
+       NO_NEIGHBOR_CMD2 "maximum-prefix <1-4294967295>",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Maximum number of prefix accept from this peer\n"
+       "maximum no. of prefix limit\n")
+
+ALIAS (no_neighbor_maximum_prefix,
+       no_neighbor_maximum_prefix_val2_cmd,
+       NO_NEIGHBOR_CMD2 "maximum-prefix <1-4294967295> warning-only",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Maximum number of prefix accept from this peer\n"
+       "maximum no. of prefix limit\n"
+       "Only give warning message when limit is exceeded\n")
+
+/* "neighbor allowas-in" */
+DEFUN (neighbor_allowas_in,
+       neighbor_allowas_in_cmd,
+       NEIGHBOR_CMD2 "allowas-in",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Accept as-path with my AS present in it\n")
+{
+  int ret;
+  struct peer *peer;
+  int allow_num;
+
+  peer = peer_and_group_lookup_vty (vty, argv[0]);
+  if (! peer)
+    return CMD_WARNING;
+
+  if (argc == 1)
+    allow_num = 3;
+  else
+    VTY_GET_INTEGER_RANGE ("AS number", allow_num, argv[1], 1, 10);
+
+  ret = peer_allowas_in_set (peer, bgp_node_afi (vty), bgp_node_safi (vty),
+			     allow_num);
+
+  return bgp_vty_return (vty, ret);
+}
+
+ALIAS (neighbor_allowas_in,
+       neighbor_allowas_in_arg_cmd,
+       NEIGHBOR_CMD2 "allowas-in <1-10>",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Accept as-path with my AS present in it\n"
+       "Number of occurances of AS number\n")
+
+DEFUN (no_neighbor_allowas_in,
+       no_neighbor_allowas_in_cmd,
+       NO_NEIGHBOR_CMD2 "allowas-in",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "allow local ASN appears in aspath attribute\n")
+{
+  int ret;
+  struct peer *peer;
+
+  peer = peer_and_group_lookup_vty (vty, argv[0]);
+  if (! peer)
+    return CMD_WARNING;
+
+  ret = peer_allowas_in_unset (peer, bgp_node_afi (vty), bgp_node_safi (vty));
+
+  return bgp_vty_return (vty, ret);
+}
+
+/* Address family configuration.  */
+DEFUN (address_family_ipv4,
+       address_family_ipv4_cmd,
+       "address-family ipv4",
+       "Enter Address Family command mode\n"
+       "Address family\n")
+{
+  vty->node = BGP_IPV4_NODE;
+  return CMD_SUCCESS;
+}
+
+DEFUN (address_family_ipv4_safi,
+       address_family_ipv4_safi_cmd,
+       "address-family ipv4 (unicast|multicast)",
+       "Enter Address Family command mode\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    vty->node = BGP_IPV4M_NODE;
+  else
+    vty->node = BGP_IPV4_NODE;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (address_family_ipv6_unicast,
+       address_family_ipv6_unicast_cmd,
+       "address-family ipv6 unicast",
+       "Enter Address Family command mode\n"
+       "Address family\n"
+       "unicast\n")
+{
+  vty->node = BGP_IPV6_NODE;
+  return CMD_SUCCESS;
+}
+
+ALIAS (address_family_ipv6_unicast,
+       address_family_ipv6_cmd,
+       "address-family ipv6",
+       "Enter Address Family command mode\n"
+       "Address family\n")
+
+DEFUN (address_family_vpnv4,
+       address_family_vpnv4_cmd,
+       "address-family vpnv4",
+       "Enter Address Family command mode\n"
+       "Address family\n")
+{
+  vty->node = BGP_VPNV4_NODE;
+  return CMD_SUCCESS;
+}
+
+ALIAS (address_family_vpnv4,
+       address_family_vpnv4_unicast_cmd,
+       "address-family vpnv4 unicast",
+       "Enter Address Family command mode\n"
+       "Address family\n"
+       "Address Family Modifier\n")
+
+DEFUN (exit_address_family,
+       exit_address_family_cmd,
+       "exit-address-family",
+       "Exit from Address Family configuration mode\n")
+{
+  if (vty->node == BGP_IPV4M_NODE
+      || vty->node == BGP_VPNV4_NODE
+      || vty->node == BGP_IPV6_NODE)
+    vty->node = BGP_NODE;
+  return CMD_SUCCESS;
+}
+
+/* BGP clear sort. */
+enum clear_sort
+{
+  clear_all,
+  clear_peer,
+  clear_group,
+  clear_external,
+  clear_as
+};
+
+void
+bgp_clear_vty_error (struct vty *vty, struct peer *peer, afi_t afi,
+		     safi_t safi, int error)
+{
+  switch (error)
+    {
+    case BGP_ERR_AF_UNCONFIGURED:
+      vty_out (vty,
+	       "%%BGP: Enable %s %s address family for the neighbor %s%s",
+	       afi == AFI_IP6 ? "IPv6" : safi == SAFI_MPLS_VPN ? "VPNv4" : "IPv4",
+	       safi == SAFI_MULTICAST ? "Multicast" : "Unicast",
+	       peer->host, VTY_NEWLINE);
+      break;
+    case BGP_ERR_SOFT_RECONFIG_UNCONFIGURED:
+      vty_out (vty, "%%BGP: Inbound soft reconfig for %s not possible as it%s      has neither refresh capability, nor inbound soft reconfig%s", peer->host, VTY_NEWLINE, VTY_NEWLINE);
+      break;
+    default:
+      break;
+    }
+}
+
+/* `clear ip bgp' functions. */
+int
+bgp_clear (struct vty *vty, struct bgp *bgp,  afi_t afi, safi_t safi,
+           enum clear_sort sort,enum bgp_clear_type stype, char *arg)
+{
+  int ret;
+  struct peer *peer;
+  struct listnode *nn;
+
+  /* Clear all neighbors. */
+  if (sort == clear_all)
+    {
+      LIST_LOOP (bgp->peer, peer, nn)
+	{
+	  if (stype == BGP_CLEAR_SOFT_NONE)
+	    ret = peer_clear (peer);
+	  else
+	    ret = peer_clear_soft (peer, afi, safi, stype);
+
+	  if (ret < 0)
+	    bgp_clear_vty_error (vty, peer, afi, safi, ret);
+	}
+      return 0;
+    }
+
+  /* Clear specified neighbors. */
+  if (sort == clear_peer)
+    {
+      union sockunion su;
+      int ret;
+
+      /* Make sockunion for lookup. */
+      ret = str2sockunion (arg, &su);
+      if (ret < 0)
+	{
+	  vty_out (vty, "Malformed address: %s%s", arg, VTY_NEWLINE);
+	  return -1;
+	}
+      peer = peer_lookup (bgp, &su);
+      if (! peer)
+	{
+	  vty_out (vty, "%%BGP: Unknown neighbor - \"%s\"%s", arg, VTY_NEWLINE);
+	  return -1;
+	}
+
+      if (stype == BGP_CLEAR_SOFT_NONE)
+	ret = peer_clear (peer);
+      else
+	ret = peer_clear_soft (peer, afi, safi, stype);
+
+      if (ret < 0)
+	bgp_clear_vty_error (vty, peer, afi, safi, ret);
+
+      return 0;
+    }
+
+  /* Clear all peer-group members. */
+  if (sort == clear_group)
+    {
+      struct peer_group *group;
+
+      group = peer_group_lookup (bgp, arg);
+      if (! group)
+	{
+	  vty_out (vty, "%%BGP: No such peer-group %s%s", arg, VTY_NEWLINE);
+	  return -1; 
+	}
+
+      LIST_LOOP (group->peer, peer, nn)
+	{
+	  if (stype == BGP_CLEAR_SOFT_NONE)
+	    {
+	      ret = peer_clear (peer);
+	      continue;
+	    }
+
+	  if (! peer->af_group[afi][safi])
+	    continue;
+
+	  ret = peer_clear_soft (peer, afi, safi, stype);
+
+	  if (ret < 0)
+	    bgp_clear_vty_error (vty, peer, afi, safi, ret);
+	}
+      return 0;
+    }
+
+  if (sort == clear_external)
+    {
+      LIST_LOOP (bgp->peer, peer, nn)
+	{
+	  if (peer_sort (peer) == BGP_PEER_IBGP) 
+	    continue;
+
+	  if (stype == BGP_CLEAR_SOFT_NONE)
+	    ret = peer_clear (peer);
+	  else
+	    ret = peer_clear_soft (peer, afi, safi, stype);
+
+	  if (ret < 0)
+	    bgp_clear_vty_error (vty, peer, afi, safi, ret);
+	}
+      return 0;
+    }
+
+  if (sort == clear_as)
+    {
+      as_t as;
+      unsigned long as_ul;
+      char *endptr = NULL;
+      int find = 0;
+
+      as_ul = strtoul(arg, &endptr, 10);
+
+      if ((as_ul == ULONG_MAX) || (*endptr != '\0') || (as_ul > USHRT_MAX))
+	{
+	  vty_out (vty, "Invalid AS number%s", VTY_NEWLINE); 
+	  return -1;
+	}
+      as = (as_t) as_ul;
+
+      LIST_LOOP (bgp->peer, peer, nn)
+	{
+	  if (peer->as != as) 
+	    continue;
+
+	  find = 1;
+	  if (stype == BGP_CLEAR_SOFT_NONE)
+	    ret = peer_clear (peer);
+	  else
+	    ret = peer_clear_soft (peer, afi, safi, stype);
+
+	  if (ret < 0)
+	    bgp_clear_vty_error (vty, peer, afi, safi, ret);
+	}
+      if (! find)
+	vty_out (vty, "%%BGP: No peer is configured with AS %s%s", arg,
+		 VTY_NEWLINE);
+      return 0;
+    }
+
+  return 0;
+}
+
+int
+bgp_clear_vty (struct vty *vty, char *name, afi_t afi, safi_t safi,
+               enum clear_sort sort, enum bgp_clear_type stype, char *arg)  
+{
+  int ret;
+  struct bgp *bgp;
+
+  /* BGP structure lookup. */
+  if (name)
+    {
+      bgp = bgp_lookup_by_name (name);
+      if (bgp == NULL)
+        {
+          vty_out (vty, "Can't find BGP view %s%s", name, VTY_NEWLINE);
+          return CMD_WARNING;
+        }
+    }
+  else
+    {
+      bgp = bgp_get_default ();
+      if (bgp == NULL)
+        {
+          vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
+          return CMD_WARNING;
+        }
+    }
+
+  ret =  bgp_clear (vty, bgp, afi, safi, sort, stype, arg);
+  if (ret < 0)
+    return CMD_WARNING;
+
+  return CMD_SUCCESS;
+}
+  
+DEFUN (clear_ip_bgp_all,
+       clear_ip_bgp_all_cmd,
+       "clear ip bgp *",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n")
+{
+  if (argc == 1)
+    return bgp_clear_vty (vty, argv[0], 0, 0, clear_all, BGP_CLEAR_SOFT_NONE, NULL);    
+
+  return bgp_clear_vty (vty, NULL, 0, 0, clear_all, BGP_CLEAR_SOFT_NONE, NULL);
+}
+
+ALIAS (clear_ip_bgp_all,
+       clear_bgp_all_cmd,
+       "clear bgp *",
+       CLEAR_STR
+       BGP_STR
+       "Clear all peers\n")
+
+ALIAS (clear_ip_bgp_all,
+       clear_bgp_ipv6_all_cmd,
+       "clear bgp ipv6 *",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear all peers\n")
+
+ALIAS (clear_ip_bgp_all,
+       clear_ip_bgp_instance_all_cmd,
+       "clear ip bgp view WORD *",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP view\n"
+       "view name\n"
+       "Clear all peers\n")
+
+ALIAS (clear_ip_bgp_all,
+       clear_bgp_instance_all_cmd,
+       "clear bgp view WORD *",
+       CLEAR_STR
+       BGP_STR
+       "BGP view\n"
+       "view name\n"
+       "Clear all peers\n")
+
+DEFUN (clear_ip_bgp_peer,
+       clear_ip_bgp_peer_cmd, 
+       "clear ip bgp (A.B.C.D|X:X::X:X)",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP neighbor IP address to clear\n"
+       "BGP IPv6 neighbor to clear\n")
+{
+  return bgp_clear_vty (vty, NULL, 0, 0, clear_peer, BGP_CLEAR_SOFT_NONE, argv[0]);
+}
+
+ALIAS (clear_ip_bgp_peer,
+       clear_bgp_peer_cmd, 
+       "clear bgp (A.B.C.D|X:X::X:X)",
+       CLEAR_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "BGP IPv6 neighbor to clear\n")
+
+ALIAS (clear_ip_bgp_peer,
+       clear_bgp_ipv6_peer_cmd, 
+       "clear bgp ipv6 (A.B.C.D|X:X::X:X)",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "BGP neighbor address to clear\n"
+       "BGP IPv6 neighbor to clear\n")
+
+DEFUN (clear_ip_bgp_peer_group,
+       clear_ip_bgp_peer_group_cmd, 
+       "clear ip bgp peer-group WORD",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n")
+{
+  return bgp_clear_vty (vty, NULL, 0, 0, clear_group, BGP_CLEAR_SOFT_NONE, argv[0]);
+}
+
+ALIAS (clear_ip_bgp_peer_group,
+       clear_bgp_peer_group_cmd, 
+       "clear bgp peer-group WORD",
+       CLEAR_STR
+       BGP_STR
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n")
+
+ALIAS (clear_ip_bgp_peer_group,
+       clear_bgp_ipv6_peer_group_cmd, 
+       "clear bgp ipv6 peer-group WORD",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n")
+
+DEFUN (clear_ip_bgp_external,
+       clear_ip_bgp_external_cmd,
+       "clear ip bgp external",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all external peers\n")
+{
+  return bgp_clear_vty (vty, NULL, 0, 0, clear_external, BGP_CLEAR_SOFT_NONE, NULL);
+}
+
+ALIAS (clear_ip_bgp_external,
+       clear_bgp_external_cmd, 
+       "clear bgp external",
+       CLEAR_STR
+       BGP_STR
+       "Clear all external peers\n")
+
+ALIAS (clear_ip_bgp_external,
+       clear_bgp_ipv6_external_cmd, 
+       "clear bgp ipv6 external",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear all external peers\n")
+
+DEFUN (clear_ip_bgp_as,
+       clear_ip_bgp_as_cmd,
+       "clear ip bgp <1-65535>",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear peers with the AS number\n")
+{
+  return bgp_clear_vty (vty, NULL, 0, 0, clear_as, BGP_CLEAR_SOFT_NONE, argv[0]);
+}       
+
+ALIAS (clear_ip_bgp_as,
+       clear_bgp_as_cmd,
+       "clear bgp <1-65535>",
+       CLEAR_STR
+       BGP_STR
+       "Clear peers with the AS number\n")
+
+ALIAS (clear_ip_bgp_as,
+       clear_bgp_ipv6_as_cmd,
+       "clear bgp ipv6 <1-65535>",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear peers with the AS number\n")
+
+/* Outbound soft-reconfiguration */
+DEFUN (clear_ip_bgp_all_soft_out,
+       clear_ip_bgp_all_soft_out_cmd,
+       "clear ip bgp * soft out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+{
+  if (argc == 1)
+    return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_UNICAST, clear_all,
+                          BGP_CLEAR_SOFT_OUT, NULL);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_all,
+			BGP_CLEAR_SOFT_OUT, NULL);
+}
+
+ALIAS (clear_ip_bgp_all_soft_out,
+       clear_ip_bgp_all_out_cmd,
+       "clear ip bgp * out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Soft reconfig outbound update\n")
+
+ALIAS (clear_ip_bgp_all_soft_out,
+       clear_ip_bgp_instance_all_soft_out_cmd,
+       "clear ip bgp view WORD * soft out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP view\n"
+       "view name\n"
+       "Clear all peers\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+
+DEFUN (clear_ip_bgp_all_ipv4_soft_out,
+       clear_ip_bgp_all_ipv4_soft_out_cmd,
+       "clear ip bgp * ipv4 (unicast|multicast) soft out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_all,
+			  BGP_CLEAR_SOFT_OUT, NULL);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_all,
+			BGP_CLEAR_SOFT_OUT, NULL);
+}
+
+ALIAS (clear_ip_bgp_all_ipv4_soft_out,
+       clear_ip_bgp_all_ipv4_out_cmd,
+       "clear ip bgp * ipv4 (unicast|multicast) out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig outbound update\n")
+
+DEFUN (clear_ip_bgp_instance_all_ipv4_soft_out,
+       clear_ip_bgp_instance_all_ipv4_soft_out_cmd,
+       "clear ip bgp view WORD * ipv4 (unicast|multicast) soft out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP view\n"
+       "view name\n"
+       "Clear all peers\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig outbound update\n")
+{
+  if (strncmp (argv[1], "m", 1) == 0)
+    return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_MULTICAST, clear_all,
+                          BGP_CLEAR_SOFT_OUT, NULL);
+
+  return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_UNICAST, clear_all,
+                        BGP_CLEAR_SOFT_OUT, NULL);
+}
+
+DEFUN (clear_ip_bgp_all_vpnv4_soft_out,
+       clear_ip_bgp_all_vpnv4_soft_out_cmd,
+       "clear ip bgp * vpnv4 unicast soft out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_all,
+			BGP_CLEAR_SOFT_OUT, NULL);
+}
+
+ALIAS (clear_ip_bgp_all_vpnv4_soft_out,
+       clear_ip_bgp_all_vpnv4_out_cmd,
+       "clear ip bgp * vpnv4 unicast out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Soft reconfig outbound update\n")
+
+DEFUN (clear_bgp_all_soft_out,
+       clear_bgp_all_soft_out_cmd,
+       "clear bgp * soft out",
+       CLEAR_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+{
+  if (argc == 1)
+    return bgp_clear_vty (vty, argv[0], AFI_IP6, SAFI_UNICAST, clear_all,
+                          BGP_CLEAR_SOFT_OUT, NULL);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_all,
+			BGP_CLEAR_SOFT_OUT, NULL);
+}
+
+ALIAS (clear_bgp_all_soft_out,
+       clear_bgp_instance_all_soft_out_cmd,
+       "clear bgp view WORD * soft out",
+       CLEAR_STR
+       BGP_STR
+       "BGP view\n"
+       "view name\n"
+       "Clear all peers\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+
+ALIAS (clear_bgp_all_soft_out,
+       clear_bgp_all_out_cmd,
+       "clear bgp * out",
+       CLEAR_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Soft reconfig outbound update\n")
+
+ALIAS (clear_bgp_all_soft_out,
+       clear_bgp_ipv6_all_soft_out_cmd,
+       "clear bgp ipv6 * soft out",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear all peers\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+
+ALIAS (clear_bgp_all_soft_out,
+       clear_bgp_ipv6_all_out_cmd,
+       "clear bgp ipv6 * out",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear all peers\n"
+       "Soft reconfig outbound update\n")
+
+DEFUN (clear_ip_bgp_peer_soft_out,
+       clear_ip_bgp_peer_soft_out_cmd,
+       "clear ip bgp A.B.C.D soft out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_peer,
+			BGP_CLEAR_SOFT_OUT, argv[0]);
+}
+
+ALIAS (clear_ip_bgp_peer_soft_out,
+       clear_ip_bgp_peer_out_cmd,
+       "clear ip bgp A.B.C.D out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "Soft reconfig outbound update\n")
+
+DEFUN (clear_ip_bgp_peer_ipv4_soft_out,
+       clear_ip_bgp_peer_ipv4_soft_out_cmd,
+       "clear ip bgp A.B.C.D ipv4 (unicast|multicast) soft out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+{
+  if (strncmp (argv[1], "m", 1) == 0)
+    return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_peer,
+			  BGP_CLEAR_SOFT_OUT, argv[0]);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_peer,
+			BGP_CLEAR_SOFT_OUT, argv[0]);
+}
+
+ALIAS (clear_ip_bgp_peer_ipv4_soft_out,
+       clear_ip_bgp_peer_ipv4_out_cmd,
+       "clear ip bgp A.B.C.D ipv4 (unicast|multicast) out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig outbound update\n")
+
+DEFUN (clear_ip_bgp_peer_vpnv4_soft_out,
+       clear_ip_bgp_peer_vpnv4_soft_out_cmd,
+       "clear ip bgp A.B.C.D vpnv4 unicast soft out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_peer,
+			BGP_CLEAR_SOFT_OUT, argv[0]);
+}
+
+ALIAS (clear_ip_bgp_peer_vpnv4_soft_out,
+       clear_ip_bgp_peer_vpnv4_out_cmd,
+       "clear ip bgp A.B.C.D vpnv4 unicast out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Soft reconfig outbound update\n")
+
+DEFUN (clear_bgp_peer_soft_out,
+       clear_bgp_peer_soft_out_cmd,
+       "clear bgp (A.B.C.D|X:X::X:X) soft out",
+       CLEAR_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "BGP IPv6 neighbor to clear\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_peer,
+			BGP_CLEAR_SOFT_OUT, argv[0]);
+}
+
+ALIAS (clear_bgp_peer_soft_out,
+       clear_bgp_ipv6_peer_soft_out_cmd,
+       "clear bgp ipv6 (A.B.C.D|X:X::X:X) soft out",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "BGP neighbor address to clear\n"
+       "BGP IPv6 neighbor to clear\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+
+ALIAS (clear_bgp_peer_soft_out,
+       clear_bgp_peer_out_cmd,
+       "clear bgp (A.B.C.D|X:X::X:X) out",
+       CLEAR_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "BGP IPv6 neighbor to clear\n"
+       "Soft reconfig outbound update\n")
+
+ALIAS (clear_bgp_peer_soft_out,
+       clear_bgp_ipv6_peer_out_cmd,
+       "clear bgp ipv6 (A.B.C.D|X:X::X:X) out",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "BGP neighbor address to clear\n"
+       "BGP IPv6 neighbor to clear\n"
+       "Soft reconfig outbound update\n")
+
+DEFUN (clear_ip_bgp_peer_group_soft_out,
+       clear_ip_bgp_peer_group_soft_out_cmd, 
+       "clear ip bgp peer-group WORD soft out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_group,
+			BGP_CLEAR_SOFT_OUT, argv[0]);
+}
+
+ALIAS (clear_ip_bgp_peer_group_soft_out,
+       clear_ip_bgp_peer_group_out_cmd, 
+       "clear ip bgp peer-group WORD out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Soft reconfig outbound update\n")
+
+DEFUN (clear_ip_bgp_peer_group_ipv4_soft_out,
+       clear_ip_bgp_peer_group_ipv4_soft_out_cmd,
+       "clear ip bgp peer-group WORD ipv4 (unicast|multicast) soft out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+{
+  if (strncmp (argv[1], "m", 1) == 0)
+    return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_group,
+			  BGP_CLEAR_SOFT_OUT, argv[0]);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_group,
+			BGP_CLEAR_SOFT_OUT, argv[0]);
+}
+
+ALIAS (clear_ip_bgp_peer_group_ipv4_soft_out,
+       clear_ip_bgp_peer_group_ipv4_out_cmd,
+       "clear ip bgp peer-group WORD ipv4 (unicast|multicast) out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig outbound update\n")
+
+DEFUN (clear_bgp_peer_group_soft_out,
+       clear_bgp_peer_group_soft_out_cmd,
+       "clear bgp peer-group WORD soft out",
+       CLEAR_STR
+       BGP_STR
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_group,
+			BGP_CLEAR_SOFT_OUT, argv[0]);
+}
+
+ALIAS (clear_bgp_peer_group_soft_out,
+       clear_bgp_ipv6_peer_group_soft_out_cmd,
+       "clear bgp ipv6 peer-group WORD soft out",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+
+ALIAS (clear_bgp_peer_group_soft_out,
+       clear_bgp_peer_group_out_cmd,
+       "clear bgp peer-group WORD out",
+       CLEAR_STR
+       BGP_STR
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Soft reconfig outbound update\n")
+
+ALIAS (clear_bgp_peer_group_soft_out,
+       clear_bgp_ipv6_peer_group_out_cmd,
+       "clear bgp ipv6 peer-group WORD out",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Soft reconfig outbound update\n")
+
+DEFUN (clear_ip_bgp_external_soft_out,
+       clear_ip_bgp_external_soft_out_cmd, 
+       "clear ip bgp external soft out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all external peers\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_external,
+			BGP_CLEAR_SOFT_OUT, NULL);
+}
+
+ALIAS (clear_ip_bgp_external_soft_out,
+       clear_ip_bgp_external_out_cmd, 
+       "clear ip bgp external out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all external peers\n"
+       "Soft reconfig outbound update\n")
+
+DEFUN (clear_ip_bgp_external_ipv4_soft_out,
+       clear_ip_bgp_external_ipv4_soft_out_cmd,
+       "clear ip bgp external ipv4 (unicast|multicast) soft out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all external peers\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_external,
+			  BGP_CLEAR_SOFT_OUT, NULL);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_external,
+			BGP_CLEAR_SOFT_OUT, NULL);
+}
+
+ALIAS (clear_ip_bgp_external_ipv4_soft_out,
+       clear_ip_bgp_external_ipv4_out_cmd,
+       "clear ip bgp external ipv4 (unicast|multicast) out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all external peers\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig outbound update\n")
+
+DEFUN (clear_bgp_external_soft_out,
+       clear_bgp_external_soft_out_cmd,
+       "clear bgp external soft out",
+       CLEAR_STR
+       BGP_STR
+       "Clear all external peers\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_external,
+			BGP_CLEAR_SOFT_OUT, NULL);
+}
+
+ALIAS (clear_bgp_external_soft_out,
+       clear_bgp_ipv6_external_soft_out_cmd,
+       "clear bgp ipv6 external soft out",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear all external peers\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+
+ALIAS (clear_bgp_external_soft_out,
+       clear_bgp_external_out_cmd,
+       "clear bgp external out",
+       CLEAR_STR
+       BGP_STR
+       "Clear all external peers\n"
+       "Soft reconfig outbound update\n")
+
+ALIAS (clear_bgp_external_soft_out,
+       clear_bgp_ipv6_external_out_cmd,
+       "clear bgp ipv6 external WORD out",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear all external peers\n"
+       "Soft reconfig outbound update\n")
+
+DEFUN (clear_ip_bgp_as_soft_out,
+       clear_ip_bgp_as_soft_out_cmd,
+       "clear ip bgp <1-65535> soft out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_as,
+			BGP_CLEAR_SOFT_OUT, argv[0]);
+}
+
+ALIAS (clear_ip_bgp_as_soft_out,
+       clear_ip_bgp_as_out_cmd,
+       "clear ip bgp <1-65535> out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Soft reconfig outbound update\n")
+
+DEFUN (clear_ip_bgp_as_ipv4_soft_out,
+       clear_ip_bgp_as_ipv4_soft_out_cmd,
+       "clear ip bgp <1-65535> ipv4 (unicast|multicast) soft out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+{
+  if (strncmp (argv[1], "m", 1) == 0)
+    return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_as,
+			  BGP_CLEAR_SOFT_OUT, argv[0]);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_as,
+			BGP_CLEAR_SOFT_OUT, argv[0]);
+}
+
+ALIAS (clear_ip_bgp_as_ipv4_soft_out,
+       clear_ip_bgp_as_ipv4_out_cmd,
+       "clear ip bgp <1-65535> ipv4 (unicast|multicast) out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig outbound update\n")
+
+DEFUN (clear_ip_bgp_as_vpnv4_soft_out,
+       clear_ip_bgp_as_vpnv4_soft_out_cmd,
+       "clear ip bgp <1-65535> vpnv4 unicast soft out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_as,
+			BGP_CLEAR_SOFT_OUT, argv[0]);
+}
+
+ALIAS (clear_ip_bgp_as_vpnv4_soft_out,
+       clear_ip_bgp_as_vpnv4_out_cmd,
+       "clear ip bgp <1-65535> vpnv4 unicast out",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Soft reconfig outbound update\n")
+
+DEFUN (clear_bgp_as_soft_out,
+       clear_bgp_as_soft_out_cmd,
+       "clear bgp <1-65535> soft out",
+       CLEAR_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_as,
+			BGP_CLEAR_SOFT_OUT, argv[0]);
+}
+
+ALIAS (clear_bgp_as_soft_out,
+       clear_bgp_ipv6_as_soft_out_cmd,
+       "clear bgp ipv6 <1-65535> soft out",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear peers with the AS number\n"
+       "Soft reconfig\n"
+       "Soft reconfig outbound update\n")
+
+ALIAS (clear_bgp_as_soft_out,
+       clear_bgp_as_out_cmd,
+       "clear bgp <1-65535> out",
+       CLEAR_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Soft reconfig outbound update\n")
+
+ALIAS (clear_bgp_as_soft_out,
+       clear_bgp_ipv6_as_out_cmd,
+       "clear bgp ipv6 <1-65535> out",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear peers with the AS number\n"
+       "Soft reconfig outbound update\n")
+
+/* Inbound soft-reconfiguration */
+DEFUN (clear_ip_bgp_all_soft_in,
+       clear_ip_bgp_all_soft_in_cmd,
+       "clear ip bgp * soft in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+{
+  if (argc == 1)
+    return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_UNICAST, clear_all,
+                          BGP_CLEAR_SOFT_IN, NULL);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_all,
+			BGP_CLEAR_SOFT_IN, NULL);
+}
+
+ALIAS (clear_ip_bgp_all_soft_in,
+       clear_ip_bgp_instance_all_soft_in_cmd,
+       "clear ip bgp view WORD * soft in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP view\n"
+       "view name\n"
+       "Clear all peers\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+
+ALIAS (clear_ip_bgp_all_soft_in,
+       clear_ip_bgp_all_in_cmd,
+       "clear ip bgp * in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Soft reconfig inbound update\n")
+
+DEFUN (clear_ip_bgp_all_in_prefix_filter,
+       clear_ip_bgp_all_in_prefix_filter_cmd,
+       "clear ip bgp * in prefix-filter",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Soft reconfig inbound update\n"
+       "Push out prefix-list ORF and do inbound soft reconfig\n")
+{
+  if (argc== 1)
+    return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_UNICAST, clear_all,
+                          BGP_CLEAR_SOFT_IN_ORF_PREFIX, NULL);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_all,
+			BGP_CLEAR_SOFT_IN_ORF_PREFIX, NULL);
+}
+
+ALIAS (clear_ip_bgp_all_in_prefix_filter,
+       clear_ip_bgp_instance_all_in_prefix_filter_cmd,
+       "clear ip bgp view WORD * in prefix-filter",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP view\n"
+       "view name\n"
+       "Clear all peers\n"
+       "Soft reconfig inbound update\n"
+       "Push out prefix-list ORF and do inbound soft reconfig\n")
+
+
+DEFUN (clear_ip_bgp_all_ipv4_soft_in,
+       clear_ip_bgp_all_ipv4_soft_in_cmd,
+       "clear ip bgp * ipv4 (unicast|multicast) soft in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_all,
+			  BGP_CLEAR_SOFT_IN, NULL);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_all,
+			BGP_CLEAR_SOFT_IN, NULL);
+}
+
+ALIAS (clear_ip_bgp_all_ipv4_soft_in,
+       clear_ip_bgp_all_ipv4_in_cmd,
+       "clear ip bgp * ipv4 (unicast|multicast) in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig inbound update\n")
+
+DEFUN (clear_ip_bgp_instance_all_ipv4_soft_in,
+       clear_ip_bgp_instance_all_ipv4_soft_in_cmd,
+       "clear ip bgp view WORD * ipv4 (unicast|multicast) soft in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP view\n"
+       "view name\n"
+       "Clear all peers\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+{
+  if (strncmp (argv[1], "m", 1) == 0)
+    return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_MULTICAST, clear_all,
+                          BGP_CLEAR_SOFT_IN, NULL);
+
+  return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_UNICAST, clear_all,
+                        BGP_CLEAR_SOFT_IN, NULL);
+}
+
+DEFUN (clear_ip_bgp_all_ipv4_in_prefix_filter,
+       clear_ip_bgp_all_ipv4_in_prefix_filter_cmd,
+       "clear ip bgp * ipv4 (unicast|multicast) in prefix-filter",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig inbound update\n"
+       "Push out prefix-list ORF and do inbound soft reconfig\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_all,
+			  BGP_CLEAR_SOFT_IN_ORF_PREFIX, NULL);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_all,
+			BGP_CLEAR_SOFT_IN_ORF_PREFIX, NULL);
+}
+
+DEFUN (clear_ip_bgp_instance_all_ipv4_in_prefix_filter,
+       clear_ip_bgp_instance_all_ipv4_in_prefix_filter_cmd,
+       "clear ip bgp view WORD * ipv4 (unicast|multicast) in prefix-filter",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig inbound update\n"
+       "Push out prefix-list ORF and do inbound soft reconfig\n")
+{
+  if (strncmp (argv[1], "m", 1) == 0)
+    return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_MULTICAST, clear_all,
+                          BGP_CLEAR_SOFT_IN_ORF_PREFIX, NULL);
+
+  return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_UNICAST, clear_all,
+                        BGP_CLEAR_SOFT_IN_ORF_PREFIX, NULL);
+}
+
+DEFUN (clear_ip_bgp_all_vpnv4_soft_in,
+       clear_ip_bgp_all_vpnv4_soft_in_cmd,
+       "clear ip bgp * vpnv4 unicast soft in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_all,
+			BGP_CLEAR_SOFT_IN, NULL);
+}
+
+ALIAS (clear_ip_bgp_all_vpnv4_soft_in,
+       clear_ip_bgp_all_vpnv4_in_cmd,
+       "clear ip bgp * vpnv4 unicast in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Soft reconfig inbound update\n")
+
+DEFUN (clear_bgp_all_soft_in,
+       clear_bgp_all_soft_in_cmd,
+       "clear bgp * soft in",
+       CLEAR_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+{
+  if (argc == 1)
+    return bgp_clear_vty (vty, argv[0], AFI_IP6, SAFI_UNICAST, clear_all,
+                        BGP_CLEAR_SOFT_IN, NULL);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_all,
+			BGP_CLEAR_SOFT_IN, NULL);
+}
+
+ALIAS (clear_bgp_all_soft_in,
+       clear_bgp_instance_all_soft_in_cmd,
+       "clear bgp view WORD * soft in",
+       CLEAR_STR
+       BGP_STR
+       "BGP view\n"
+       "view name\n"
+       "Clear all peers\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+
+ALIAS (clear_bgp_all_soft_in,
+       clear_bgp_ipv6_all_soft_in_cmd,
+       "clear bgp ipv6 * soft in",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear all peers\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+
+ALIAS (clear_bgp_all_soft_in,
+       clear_bgp_all_in_cmd,
+       "clear bgp * in",
+       CLEAR_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Soft reconfig inbound update\n")
+
+ALIAS (clear_bgp_all_soft_in,
+       clear_bgp_ipv6_all_in_cmd,
+       "clear bgp ipv6 * in",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear all peers\n"
+       "Soft reconfig inbound update\n")
+
+DEFUN (clear_bgp_all_in_prefix_filter,
+       clear_bgp_all_in_prefix_filter_cmd,
+       "clear bgp * in prefix-filter",
+       CLEAR_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Soft reconfig inbound update\n"
+       "Push out prefix-list ORF and do inbound soft reconfig\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_all,
+			BGP_CLEAR_SOFT_IN_ORF_PREFIX, NULL);
+}
+
+ALIAS (clear_bgp_all_in_prefix_filter,
+       clear_bgp_ipv6_all_in_prefix_filter_cmd,
+       "clear bgp ipv6 * in prefix-filter",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear all peers\n"
+       "Soft reconfig inbound update\n"
+       "Push out prefix-list ORF and do inbound soft reconfig\n")
+
+DEFUN (clear_ip_bgp_peer_soft_in,
+       clear_ip_bgp_peer_soft_in_cmd,
+       "clear ip bgp A.B.C.D soft in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_peer,
+			BGP_CLEAR_SOFT_IN, argv[0]);
+}
+
+ALIAS (clear_ip_bgp_peer_soft_in,
+       clear_ip_bgp_peer_in_cmd,
+       "clear ip bgp A.B.C.D in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "Soft reconfig inbound update\n")
+       
+DEFUN (clear_ip_bgp_peer_in_prefix_filter,
+       clear_ip_bgp_peer_in_prefix_filter_cmd,
+       "clear ip bgp A.B.C.D in prefix-filter",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "Soft reconfig inbound update\n"
+       "Push out the existing ORF prefix-list\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_peer,
+			BGP_CLEAR_SOFT_IN_ORF_PREFIX, argv[0]);
+}
+
+DEFUN (clear_ip_bgp_peer_ipv4_soft_in,
+       clear_ip_bgp_peer_ipv4_soft_in_cmd,
+       "clear ip bgp A.B.C.D ipv4 (unicast|multicast) soft in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+{
+  if (strncmp (argv[1], "m", 1) == 0)
+    return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_peer,
+			  BGP_CLEAR_SOFT_IN, argv[0]);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_peer,
+			BGP_CLEAR_SOFT_IN, argv[0]);
+}
+
+ALIAS (clear_ip_bgp_peer_ipv4_soft_in,
+       clear_ip_bgp_peer_ipv4_in_cmd,
+       "clear ip bgp A.B.C.D ipv4 (unicast|multicast) in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig inbound update\n")
+
+DEFUN (clear_ip_bgp_peer_ipv4_in_prefix_filter,
+       clear_ip_bgp_peer_ipv4_in_prefix_filter_cmd,
+       "clear ip bgp A.B.C.D ipv4 (unicast|multicast) in prefix-filter",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig inbound update\n"
+       "Push out the existing ORF prefix-list\n")
+{
+  if (strncmp (argv[1], "m", 1) == 0)
+    return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_peer,
+			  BGP_CLEAR_SOFT_IN_ORF_PREFIX, argv[0]);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_peer,
+			BGP_CLEAR_SOFT_IN_ORF_PREFIX, argv[0]);
+}
+
+DEFUN (clear_ip_bgp_peer_vpnv4_soft_in,
+       clear_ip_bgp_peer_vpnv4_soft_in_cmd,
+       "clear ip bgp A.B.C.D vpnv4 unicast soft in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_peer,
+			BGP_CLEAR_SOFT_IN, argv[0]);
+}
+
+ALIAS (clear_ip_bgp_peer_vpnv4_soft_in,
+       clear_ip_bgp_peer_vpnv4_in_cmd,
+       "clear ip bgp A.B.C.D vpnv4 unicast in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Soft reconfig inbound update\n")
+
+DEFUN (clear_bgp_peer_soft_in,
+       clear_bgp_peer_soft_in_cmd,
+       "clear bgp (A.B.C.D|X:X::X:X) soft in",
+       CLEAR_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "BGP IPv6 neighbor to clear\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_peer,
+			BGP_CLEAR_SOFT_IN, argv[0]);
+}
+
+ALIAS (clear_bgp_peer_soft_in,
+       clear_bgp_ipv6_peer_soft_in_cmd,
+       "clear bgp ipv6 (A.B.C.D|X:X::X:X) soft in",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "BGP neighbor address to clear\n"
+       "BGP IPv6 neighbor to clear\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+
+ALIAS (clear_bgp_peer_soft_in,
+       clear_bgp_peer_in_cmd,
+       "clear bgp (A.B.C.D|X:X::X:X) in",
+       CLEAR_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "BGP IPv6 neighbor to clear\n"
+       "Soft reconfig inbound update\n")
+
+ALIAS (clear_bgp_peer_soft_in,
+       clear_bgp_ipv6_peer_in_cmd,
+       "clear bgp ipv6 (A.B.C.D|X:X::X:X) in",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "BGP neighbor address to clear\n"
+       "BGP IPv6 neighbor to clear\n"
+       "Soft reconfig inbound update\n")
+
+DEFUN (clear_bgp_peer_in_prefix_filter,
+       clear_bgp_peer_in_prefix_filter_cmd,
+       "clear bgp (A.B.C.D|X:X::X:X) in prefix-filter",
+       CLEAR_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "BGP IPv6 neighbor to clear\n"
+       "Soft reconfig inbound update\n"
+       "Push out the existing ORF prefix-list\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_peer,
+			BGP_CLEAR_SOFT_IN_ORF_PREFIX, argv[0]);
+}
+
+ALIAS (clear_bgp_peer_in_prefix_filter,
+       clear_bgp_ipv6_peer_in_prefix_filter_cmd,
+       "clear bgp ipv6 (A.B.C.D|X:X::X:X) in prefix-filter",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "BGP neighbor address to clear\n"
+       "BGP IPv6 neighbor to clear\n"
+       "Soft reconfig inbound update\n"
+       "Push out the existing ORF prefix-list\n")
+
+DEFUN (clear_ip_bgp_peer_group_soft_in,
+       clear_ip_bgp_peer_group_soft_in_cmd,
+       "clear ip bgp peer-group WORD soft in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_group,
+			BGP_CLEAR_SOFT_IN, argv[0]);
+}
+
+ALIAS (clear_ip_bgp_peer_group_soft_in,
+       clear_ip_bgp_peer_group_in_cmd,
+       "clear ip bgp peer-group WORD in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Soft reconfig inbound update\n")
+
+DEFUN (clear_ip_bgp_peer_group_in_prefix_filter,
+       clear_ip_bgp_peer_group_in_prefix_filter_cmd,
+       "clear ip bgp peer-group WORD in prefix-filter",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Soft reconfig inbound update\n"
+       "Push out prefix-list ORF and do inbound soft reconfig\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_group,
+			BGP_CLEAR_SOFT_IN_ORF_PREFIX, argv[0]);
+}
+
+DEFUN (clear_ip_bgp_peer_group_ipv4_soft_in,
+       clear_ip_bgp_peer_group_ipv4_soft_in_cmd,
+       "clear ip bgp peer-group WORD ipv4 (unicast|multicast) soft in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+{
+  if (strncmp (argv[1], "m", 1) == 0)
+    return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_group,
+			  BGP_CLEAR_SOFT_IN, argv[0]);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_group,
+			BGP_CLEAR_SOFT_IN, argv[0]);
+}
+
+ALIAS (clear_ip_bgp_peer_group_ipv4_soft_in,
+       clear_ip_bgp_peer_group_ipv4_in_cmd,
+       "clear ip bgp peer-group WORD ipv4 (unicast|multicast) in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig inbound update\n")
+
+DEFUN (clear_ip_bgp_peer_group_ipv4_in_prefix_filter,
+       clear_ip_bgp_peer_group_ipv4_in_prefix_filter_cmd,
+       "clear ip bgp peer-group WORD ipv4 (unicast|multicast) in prefix-filter",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig inbound update\n"
+       "Push out prefix-list ORF and do inbound soft reconfig\n")
+{
+  if (strncmp (argv[1], "m", 1) == 0)
+    return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_group,
+			  BGP_CLEAR_SOFT_IN_ORF_PREFIX, argv[0]);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_group,
+			BGP_CLEAR_SOFT_IN_ORF_PREFIX, argv[0]);
+}
+
+DEFUN (clear_bgp_peer_group_soft_in,
+       clear_bgp_peer_group_soft_in_cmd,
+       "clear bgp peer-group WORD soft in",
+       CLEAR_STR
+       BGP_STR
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_group,
+			BGP_CLEAR_SOFT_IN, argv[0]);
+}
+
+ALIAS (clear_bgp_peer_group_soft_in,
+       clear_bgp_ipv6_peer_group_soft_in_cmd,
+       "clear bgp ipv6 peer-group WORD soft in",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+
+ALIAS (clear_bgp_peer_group_soft_in,
+       clear_bgp_peer_group_in_cmd,
+       "clear bgp peer-group WORD in",
+       CLEAR_STR
+       BGP_STR
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Soft reconfig inbound update\n")
+
+ALIAS (clear_bgp_peer_group_soft_in,
+       clear_bgp_ipv6_peer_group_in_cmd,
+       "clear bgp ipv6 peer-group WORD in",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Soft reconfig inbound update\n")
+
+DEFUN (clear_bgp_peer_group_in_prefix_filter,
+       clear_bgp_peer_group_in_prefix_filter_cmd,
+       "clear bgp peer-group WORD in prefix-filter",
+       CLEAR_STR
+       BGP_STR
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Soft reconfig inbound update\n"
+       "Push out prefix-list ORF and do inbound soft reconfig\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_group,
+			BGP_CLEAR_SOFT_IN_ORF_PREFIX, argv[0]);
+}
+
+ALIAS (clear_bgp_peer_group_in_prefix_filter,
+       clear_bgp_ipv6_peer_group_in_prefix_filter_cmd,
+       "clear bgp ipv6 peer-group WORD in prefix-filter",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Soft reconfig inbound update\n"
+       "Push out prefix-list ORF and do inbound soft reconfig\n")
+
+DEFUN (clear_ip_bgp_external_soft_in,
+       clear_ip_bgp_external_soft_in_cmd,
+       "clear ip bgp external soft in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all external peers\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_external,
+			BGP_CLEAR_SOFT_IN, NULL);
+}
+
+ALIAS (clear_ip_bgp_external_soft_in,
+       clear_ip_bgp_external_in_cmd,
+       "clear ip bgp external in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all external peers\n"
+       "Soft reconfig inbound update\n")
+
+DEFUN (clear_ip_bgp_external_in_prefix_filter,
+       clear_ip_bgp_external_in_prefix_filter_cmd,
+       "clear ip bgp external in prefix-filter",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all external peers\n"
+       "Soft reconfig inbound update\n"
+       "Push out prefix-list ORF and do inbound soft reconfig\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_external,
+			BGP_CLEAR_SOFT_IN_ORF_PREFIX, NULL);
+}
+
+DEFUN (clear_ip_bgp_external_ipv4_soft_in,
+       clear_ip_bgp_external_ipv4_soft_in_cmd,
+       "clear ip bgp external ipv4 (unicast|multicast) soft in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all external peers\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_external,
+			  BGP_CLEAR_SOFT_IN, NULL);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_external,
+			BGP_CLEAR_SOFT_IN, NULL);
+}
+
+ALIAS (clear_ip_bgp_external_ipv4_soft_in,
+       clear_ip_bgp_external_ipv4_in_cmd,
+       "clear ip bgp external ipv4 (unicast|multicast) in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all external peers\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig inbound update\n")
+
+DEFUN (clear_ip_bgp_external_ipv4_in_prefix_filter,
+       clear_ip_bgp_external_ipv4_in_prefix_filter_cmd,
+       "clear ip bgp external ipv4 (unicast|multicast) in prefix-filter",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all external peers\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig inbound update\n"
+       "Push out prefix-list ORF and do inbound soft reconfig\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_external,
+			  BGP_CLEAR_SOFT_IN_ORF_PREFIX, NULL);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_external,
+			BGP_CLEAR_SOFT_IN_ORF_PREFIX, NULL);
+}
+
+DEFUN (clear_bgp_external_soft_in,
+       clear_bgp_external_soft_in_cmd,
+       "clear bgp external soft in",
+       CLEAR_STR
+       BGP_STR
+       "Clear all external peers\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_external,
+			BGP_CLEAR_SOFT_IN, NULL);
+}
+
+ALIAS (clear_bgp_external_soft_in,
+       clear_bgp_ipv6_external_soft_in_cmd,
+       "clear bgp ipv6 external soft in",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear all external peers\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+
+ALIAS (clear_bgp_external_soft_in,
+       clear_bgp_external_in_cmd,
+       "clear bgp external in",
+       CLEAR_STR
+       BGP_STR
+       "Clear all external peers\n"
+       "Soft reconfig inbound update\n")
+
+ALIAS (clear_bgp_external_soft_in,
+       clear_bgp_ipv6_external_in_cmd,
+       "clear bgp ipv6 external WORD in",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear all external peers\n"
+       "Soft reconfig inbound update\n")
+
+DEFUN (clear_bgp_external_in_prefix_filter,
+       clear_bgp_external_in_prefix_filter_cmd,
+       "clear bgp external in prefix-filter",
+       CLEAR_STR
+       BGP_STR
+       "Clear all external peers\n"
+       "Soft reconfig inbound update\n"
+       "Push out prefix-list ORF and do inbound soft reconfig\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_external,
+			BGP_CLEAR_SOFT_IN_ORF_PREFIX, NULL);
+}
+
+ALIAS (clear_bgp_external_in_prefix_filter,
+       clear_bgp_ipv6_external_in_prefix_filter_cmd,
+       "clear bgp ipv6 external in prefix-filter",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear all external peers\n"
+       "Soft reconfig inbound update\n"
+       "Push out prefix-list ORF and do inbound soft reconfig\n")
+
+DEFUN (clear_ip_bgp_as_soft_in,
+       clear_ip_bgp_as_soft_in_cmd,
+       "clear ip bgp <1-65535> soft in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_as,
+			BGP_CLEAR_SOFT_IN, argv[0]);
+}
+
+ALIAS (clear_ip_bgp_as_soft_in,
+       clear_ip_bgp_as_in_cmd,
+       "clear ip bgp <1-65535> in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Soft reconfig inbound update\n")
+
+DEFUN (clear_ip_bgp_as_in_prefix_filter,
+       clear_ip_bgp_as_in_prefix_filter_cmd,
+       "clear ip bgp <1-65535> in prefix-filter",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Soft reconfig inbound update\n"
+       "Push out prefix-list ORF and do inbound soft reconfig\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_as,
+			BGP_CLEAR_SOFT_IN_ORF_PREFIX, argv[0]);
+}
+
+DEFUN (clear_ip_bgp_as_ipv4_soft_in,
+       clear_ip_bgp_as_ipv4_soft_in_cmd,
+       "clear ip bgp <1-65535> ipv4 (unicast|multicast) soft in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+{
+  if (strncmp (argv[1], "m", 1) == 0)
+    return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_as,
+			  BGP_CLEAR_SOFT_IN, argv[0]);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_as,
+			BGP_CLEAR_SOFT_IN, argv[0]);
+}
+
+ALIAS (clear_ip_bgp_as_ipv4_soft_in,
+       clear_ip_bgp_as_ipv4_in_cmd,
+       "clear ip bgp <1-65535> ipv4 (unicast|multicast) in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig inbound update\n")
+
+DEFUN (clear_ip_bgp_as_ipv4_in_prefix_filter,
+       clear_ip_bgp_as_ipv4_in_prefix_filter_cmd,
+       "clear ip bgp <1-65535> ipv4 (unicast|multicast) in prefix-filter",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig inbound update\n"
+       "Push out prefix-list ORF and do inbound soft reconfig\n")
+{
+  if (strncmp (argv[1], "m", 1) == 0)
+    return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_as,
+			  BGP_CLEAR_SOFT_IN_ORF_PREFIX, argv[0]);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_as,
+			BGP_CLEAR_SOFT_IN_ORF_PREFIX, argv[0]);
+}
+
+DEFUN (clear_ip_bgp_as_vpnv4_soft_in,
+       clear_ip_bgp_as_vpnv4_soft_in_cmd,
+       "clear ip bgp <1-65535> vpnv4 unicast soft in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_as,
+			BGP_CLEAR_SOFT_IN, argv[0]);
+}
+
+ALIAS (clear_ip_bgp_as_vpnv4_soft_in,
+       clear_ip_bgp_as_vpnv4_in_cmd,
+       "clear ip bgp <1-65535> vpnv4 unicast in",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Soft reconfig inbound update\n")
+
+DEFUN (clear_bgp_as_soft_in,
+       clear_bgp_as_soft_in_cmd,
+       "clear bgp <1-65535> soft in",
+       CLEAR_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_as,
+			BGP_CLEAR_SOFT_IN, argv[0]);
+}
+
+ALIAS (clear_bgp_as_soft_in,
+       clear_bgp_ipv6_as_soft_in_cmd,
+       "clear bgp ipv6 <1-65535> soft in",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear peers with the AS number\n"
+       "Soft reconfig\n"
+       "Soft reconfig inbound update\n")
+
+ALIAS (clear_bgp_as_soft_in,
+       clear_bgp_as_in_cmd,
+       "clear bgp <1-65535> in",
+       CLEAR_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Soft reconfig inbound update\n")
+
+ALIAS (clear_bgp_as_soft_in,
+       clear_bgp_ipv6_as_in_cmd,
+       "clear bgp ipv6 <1-65535> in",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear peers with the AS number\n"
+       "Soft reconfig inbound update\n")
+
+DEFUN (clear_bgp_as_in_prefix_filter,
+       clear_bgp_as_in_prefix_filter_cmd,
+       "clear bgp <1-65535> in prefix-filter",
+       CLEAR_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Soft reconfig inbound update\n"
+       "Push out prefix-list ORF and do inbound soft reconfig\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_as,
+			BGP_CLEAR_SOFT_IN_ORF_PREFIX, argv[0]);
+}
+
+ALIAS (clear_bgp_as_in_prefix_filter,
+       clear_bgp_ipv6_as_in_prefix_filter_cmd,
+       "clear bgp ipv6 <1-65535> in prefix-filter",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear peers with the AS number\n"
+       "Soft reconfig inbound update\n"
+       "Push out prefix-list ORF and do inbound soft reconfig\n")
+
+/* Both soft-reconfiguration */
+DEFUN (clear_ip_bgp_all_soft,
+       clear_ip_bgp_all_soft_cmd,
+       "clear ip bgp * soft",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Soft reconfig\n")
+{
+  if (argc == 1)
+    return bgp_clear_vty (vty, argv[0], AFI_IP, SAFI_UNICAST, clear_all,
+                        BGP_CLEAR_SOFT_BOTH, NULL);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_all,
+			BGP_CLEAR_SOFT_BOTH, NULL);
+}
+
+ALIAS (clear_ip_bgp_all_soft,
+       clear_ip_bgp_instance_all_soft_cmd,
+       "clear ip bgp view WORD * soft",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP view\n"
+       "view name\n"
+       "Clear all peers\n"
+       "Soft reconfig\n")
+
+
+DEFUN (clear_ip_bgp_all_ipv4_soft,
+       clear_ip_bgp_all_ipv4_soft_cmd,
+       "clear ip bgp * ipv4 (unicast|multicast) soft",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Address Family Modifier\n"
+       "Soft reconfig\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_all,
+			  BGP_CLEAR_SOFT_BOTH, NULL);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_all,
+			BGP_CLEAR_SOFT_BOTH, NULL);
+}
+
+DEFUN (clear_ip_bgp_instance_all_ipv4_soft,
+       clear_ip_bgp_instance_all_ipv4_soft_cmd,
+       "clear ip bgp view WORD * ipv4 (unicast|multicast) soft",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP view\n"
+       "view name\n"
+       "Clear all peers\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Address Family Modifier\n"
+       "Soft reconfig\n")
+{
+  if (strncmp (argv[1], "m", 1) == 0)
+    return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_all,
+                          BGP_CLEAR_SOFT_BOTH, NULL);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_all,
+                        BGP_CLEAR_SOFT_BOTH, NULL);
+}
+
+DEFUN (clear_ip_bgp_all_vpnv4_soft,
+       clear_ip_bgp_all_vpnv4_soft_cmd,
+       "clear ip bgp * vpnv4 unicast soft",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Soft reconfig\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_all,
+			BGP_CLEAR_SOFT_BOTH, argv[0]);
+}
+
+DEFUN (clear_bgp_all_soft,
+       clear_bgp_all_soft_cmd,
+       "clear bgp * soft",
+       CLEAR_STR
+       BGP_STR
+       "Clear all peers\n"
+       "Soft reconfig\n")
+{
+  if (argc == 1)
+    return bgp_clear_vty (vty, argv[0], AFI_IP6, SAFI_UNICAST, clear_all,
+                        BGP_CLEAR_SOFT_BOTH, argv[0]);
+ 
+  return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_all,
+			BGP_CLEAR_SOFT_BOTH, argv[0]);
+}
+
+ALIAS (clear_bgp_all_soft,
+       clear_bgp_instance_all_soft_cmd,
+       "clear bgp view WORD * soft",
+       CLEAR_STR
+       BGP_STR
+       "BGP view\n"
+       "view name\n"
+       "Clear all peers\n"
+       "Soft reconfig\n")
+
+ALIAS (clear_bgp_all_soft,
+       clear_bgp_ipv6_all_soft_cmd,
+       "clear bgp ipv6 * soft",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear all peers\n"
+       "Soft reconfig\n")
+
+DEFUN (clear_ip_bgp_peer_soft,
+       clear_ip_bgp_peer_soft_cmd,
+       "clear ip bgp A.B.C.D soft",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "Soft reconfig\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_peer,
+			BGP_CLEAR_SOFT_BOTH, argv[0]);
+}
+
+DEFUN (clear_ip_bgp_peer_ipv4_soft,
+       clear_ip_bgp_peer_ipv4_soft_cmd,
+       "clear ip bgp A.B.C.D ipv4 (unicast|multicast) soft",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Address Family Modifier\n"
+       "Soft reconfig\n")
+{
+  if (strncmp (argv[1], "m", 1) == 0)
+    return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_peer,
+			  BGP_CLEAR_SOFT_BOTH, argv[0]);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_peer,
+			BGP_CLEAR_SOFT_BOTH, argv[0]);
+}
+
+DEFUN (clear_ip_bgp_peer_vpnv4_soft,
+       clear_ip_bgp_peer_vpnv4_soft_cmd,
+       "clear ip bgp A.B.C.D vpnv4 unicast soft",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Soft reconfig\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_peer,
+			BGP_CLEAR_SOFT_BOTH, argv[0]);
+}
+
+DEFUN (clear_bgp_peer_soft,
+       clear_bgp_peer_soft_cmd,
+       "clear bgp (A.B.C.D|X:X::X:X) soft",
+       CLEAR_STR
+       BGP_STR
+       "BGP neighbor address to clear\n"
+       "BGP IPv6 neighbor to clear\n"
+       "Soft reconfig\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_peer,
+			BGP_CLEAR_SOFT_BOTH, argv[0]);
+}
+
+ALIAS (clear_bgp_peer_soft,
+       clear_bgp_ipv6_peer_soft_cmd,
+       "clear bgp ipv6 (A.B.C.D|X:X::X:X) soft",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "BGP neighbor address to clear\n"
+       "BGP IPv6 neighbor to clear\n"
+       "Soft reconfig\n")
+
+DEFUN (clear_ip_bgp_peer_group_soft,
+       clear_ip_bgp_peer_group_soft_cmd,
+       "clear ip bgp peer-group WORD soft",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Soft reconfig\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_group,
+			BGP_CLEAR_SOFT_BOTH, argv[0]);
+}
+
+DEFUN (clear_ip_bgp_peer_group_ipv4_soft,
+       clear_ip_bgp_peer_group_ipv4_soft_cmd,
+       "clear ip bgp peer-group WORD ipv4 (unicast|multicast) soft",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig\n")
+{
+  if (strncmp (argv[1], "m", 1) == 0)
+    return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_group,
+			  BGP_CLEAR_SOFT_BOTH, argv[0]);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_group,
+			BGP_CLEAR_SOFT_BOTH, argv[0]);
+}
+
+DEFUN (clear_bgp_peer_group_soft,
+       clear_bgp_peer_group_soft_cmd,
+       "clear bgp peer-group WORD soft",
+       CLEAR_STR
+       BGP_STR
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Soft reconfig\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_group,
+			BGP_CLEAR_SOFT_BOTH, argv[0]);
+}
+
+ALIAS (clear_bgp_peer_group_soft,
+       clear_bgp_ipv6_peer_group_soft_cmd,
+       "clear bgp ipv6 peer-group WORD soft",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear all members of peer-group\n"
+       "BGP peer-group name\n"
+       "Soft reconfig\n")
+
+DEFUN (clear_ip_bgp_external_soft,
+       clear_ip_bgp_external_soft_cmd,
+       "clear ip bgp external soft",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all external peers\n"
+       "Soft reconfig\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_external,
+			BGP_CLEAR_SOFT_BOTH, NULL);
+}
+
+DEFUN (clear_ip_bgp_external_ipv4_soft,
+       clear_ip_bgp_external_ipv4_soft_cmd,
+       "clear ip bgp external ipv4 (unicast|multicast) soft",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear all external peers\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Soft reconfig\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_external,
+			  BGP_CLEAR_SOFT_BOTH, NULL);
+
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_external,
+			BGP_CLEAR_SOFT_BOTH, NULL);
+}
+
+DEFUN (clear_bgp_external_soft,
+       clear_bgp_external_soft_cmd,
+       "clear bgp external soft",
+       CLEAR_STR
+       BGP_STR
+       "Clear all external peers\n"
+       "Soft reconfig\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_external,
+			BGP_CLEAR_SOFT_BOTH, NULL);
+}
+
+ALIAS (clear_bgp_external_soft,
+       clear_bgp_ipv6_external_soft_cmd,
+       "clear bgp ipv6 external soft",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear all external peers\n"
+       "Soft reconfig\n")
+
+DEFUN (clear_ip_bgp_as_soft,
+       clear_ip_bgp_as_soft_cmd,
+       "clear ip bgp <1-65535> soft",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Soft reconfig\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_UNICAST, clear_as,
+			BGP_CLEAR_SOFT_BOTH, argv[0]);
+}
+
+DEFUN (clear_ip_bgp_as_ipv4_soft,
+       clear_ip_bgp_as_ipv4_soft_cmd,
+       "clear ip bgp <1-65535> ipv4 (unicast|multicast) soft",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Address Family Modifier\n"
+       "Soft reconfig\n")
+{
+  if (strncmp (argv[1], "m", 1) == 0)
+    return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MULTICAST, clear_as,
+			  BGP_CLEAR_SOFT_BOTH, argv[0]);
+
+  return bgp_clear_vty (vty, NULL,AFI_IP, SAFI_UNICAST, clear_as,
+			BGP_CLEAR_SOFT_BOTH, argv[0]);
+}
+
+DEFUN (clear_ip_bgp_as_vpnv4_soft,
+       clear_ip_bgp_as_vpnv4_soft_cmd,
+       "clear ip bgp <1-65535> vpnv4 unicast soft",
+       CLEAR_STR
+       IP_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Address family\n"
+       "Address Family Modifier\n"
+       "Soft reconfig\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN, clear_as,
+			BGP_CLEAR_SOFT_BOTH, argv[0]);
+}
+
+DEFUN (clear_bgp_as_soft,
+       clear_bgp_as_soft_cmd,
+       "clear bgp <1-65535> soft",
+       CLEAR_STR
+       BGP_STR
+       "Clear peers with the AS number\n"
+       "Soft reconfig\n")
+{
+  return bgp_clear_vty (vty, NULL, AFI_IP6, SAFI_UNICAST, clear_as,
+			BGP_CLEAR_SOFT_BOTH, argv[0]);
+}
+
+ALIAS (clear_bgp_as_soft,
+       clear_bgp_ipv6_as_soft_cmd,
+       "clear bgp ipv6 <1-65535> soft",
+       CLEAR_STR
+       BGP_STR
+       "Address family\n"
+       "Clear peers with the AS number\n"
+       "Soft reconfig\n")
+
+/* Show BGP peer's summary information. */
+int
+bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi)
+{
+  struct peer *peer;
+  struct listnode *nn;
+  int count = 0;
+  char timebuf[BGP_UPTIME_LEN];
+  int len;
+
+  /* Header string for each address family. */
+  static char header[] = "Neighbor        V    AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd";
+
+  LIST_LOOP (bgp->peer, peer, nn)
+    {
+      if (peer->afc[afi][safi])
+	{
+	  if (! count)
+	    {
+	      vty_out (vty,
+		       "BGP router identifier %s, local AS number %d%s",
+		       inet_ntoa (bgp->router_id), bgp->as, VTY_NEWLINE);
+	      vty_out (vty, 
+		       "%ld BGP AS-PATH entries%s", aspath_count (),
+		       VTY_NEWLINE);
+	      vty_out (vty, 
+		       "%ld BGP community entries%s", community_count (),
+		       VTY_NEWLINE);
+
+	      if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
+		vty_out (vty, "Dampening enabled.%s", VTY_NEWLINE);
+	      vty_out (vty, "%s", VTY_NEWLINE);
+	      vty_out (vty, "%s%s", header, VTY_NEWLINE);
+	    }
+	  count++;
+
+	  len = vty_out (vty, "%s", peer->host);
+	  len = 16 - len;
+	  if (len < 1)
+	    vty_out (vty, "%s%*s", VTY_NEWLINE, 16, " ");
+	  else
+	    vty_out (vty, "%*s", len, " ");
+
+	  switch (peer->version) 
+	    {
+	    case BGP_VERSION_4:
+	      vty_out (vty, "4 ");
+	      break;
+	    case BGP_VERSION_MP_4_DRAFT_00:
+	      vty_out (vty, "4-");
+	      break;
+	    }
+
+	  vty_out (vty, "%5d %7d %7d %8d %4d %4ld ",
+		   peer->as,
+		   peer->open_in + peer->update_in + peer->keepalive_in
+		   + peer->notify_in + peer->refresh_in + peer->dynamic_cap_in,
+		   peer->open_out + peer->update_out + peer->keepalive_out
+		   + peer->notify_out + peer->refresh_out
+		   + peer->dynamic_cap_out,
+		   0, 0, peer->obuf->count);
+
+	  vty_out (vty, "%8s", 
+		   peer_uptime (peer->uptime, timebuf, BGP_UPTIME_LEN));
+
+	  if (peer->status == Established)
+	    {
+	      vty_out (vty, " %8ld", peer->pcount[afi][safi]);
+	    }
+	  else
+	    {
+	      if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
+		vty_out (vty, " Idle (Admin)");
+	      else if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
+		vty_out (vty, " Idle (PfxCt)");
+	      else
+		vty_out (vty, " %-11s", LOOKUP(bgp_status_msg, peer->status));
+	    }
+
+	  vty_out (vty, "%s", VTY_NEWLINE);
+	}
+    }
+
+  if (count)
+    vty_out (vty, "%sTotal number of neighbors %d%s", VTY_NEWLINE,
+	     count, VTY_NEWLINE);
+  else
+    vty_out (vty, "No %s neighbor is configured%s",
+	     afi == AFI_IP ? "IPv4" : "IPv6", VTY_NEWLINE);
+  return CMD_SUCCESS;
+}
+
+int 
+bgp_show_summary_vty (struct vty *vty, char *name, afi_t afi, safi_t safi)
+{
+  struct bgp *bgp;
+
+  if (name)
+    {
+      bgp = bgp_lookup_by_name (name);
+      
+      if (! bgp)
+	{
+	  vty_out (vty, "%% No such BGP instance exist%s", VTY_NEWLINE); 
+	  return CMD_WARNING;
+	}
+
+      bgp_show_summary (vty, bgp, afi, safi);
+      return CMD_SUCCESS;
+    }
+  
+  bgp = bgp_get_default ();
+
+  if (bgp)
+    bgp_show_summary (vty, bgp, afi, safi);    
+ 
+  return CMD_SUCCESS;
+}
+
+/* `show ip bgp summary' commands. */
+DEFUN (show_ip_bgp_summary, 
+       show_ip_bgp_summary_cmd,
+       "show ip bgp summary",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Summary of BGP neighbor status\n")
+{
+  return bgp_show_summary_vty (vty, NULL, AFI_IP, SAFI_UNICAST);
+}
+
+DEFUN (show_ip_bgp_instance_summary,
+       show_ip_bgp_instance_summary_cmd,
+       "show ip bgp view WORD summary",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "BGP view\n"
+       "View name\n"
+       "Summary of BGP neighbor status\n")
+{
+  return bgp_show_summary_vty (vty, argv[0], AFI_IP, SAFI_UNICAST);  
+}
+
+DEFUN (show_ip_bgp_ipv4_summary, 
+       show_ip_bgp_ipv4_summary_cmd,
+       "show ip bgp ipv4 (unicast|multicast) summary",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Summary of BGP neighbor status\n")
+{
+  if (strncmp (argv[0], "m", 1) == 0)
+    return bgp_show_summary_vty (vty, NULL, AFI_IP, SAFI_MULTICAST);
+
+  return bgp_show_summary_vty (vty, NULL, AFI_IP, SAFI_UNICAST);
+}
+
+DEFUN (show_ip_bgp_instance_ipv4_summary,
+       show_ip_bgp_instance_ipv4_summary_cmd,
+       "show ip bgp view WORD ipv4 (unicast|multicast) summary",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "BGP view\n"
+       "View name\n"
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Summary of BGP neighbor status\n")
+{
+  if (strncmp (argv[1], "m", 1) == 0)
+    return bgp_show_summary_vty (vty, argv[0], AFI_IP, SAFI_MULTICAST);
+  else
+    return bgp_show_summary_vty (vty, argv[0], AFI_IP, SAFI_UNICAST);
+}
+
+DEFUN (show_ip_bgp_vpnv4_all_summary,
+       show_ip_bgp_vpnv4_all_summary_cmd,
+       "show ip bgp vpnv4 all summary",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display VPNv4 NLRI specific information\n"
+       "Display information about all VPNv4 NLRIs\n"
+       "Summary of BGP neighbor status\n")
+{
+  return bgp_show_summary_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN);
+}
+
+DEFUN (show_ip_bgp_vpnv4_rd_summary,
+       show_ip_bgp_vpnv4_rd_summary_cmd,
+       "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn summary",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display VPNv4 NLRI specific information\n"
+       "Display information for a route distinguisher\n"
+       "VPN Route Distinguisher\n"
+       "Summary of BGP neighbor status\n")
+{
+  int ret;
+  struct prefix_rd prd;
+
+  ret = str2prefix_rd (argv[0], &prd);
+  if (! ret)
+    {
+      vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_show_summary_vty (vty, NULL, AFI_IP, SAFI_MPLS_VPN);
+}
+
+#ifdef HAVE_IPV6
+DEFUN (show_bgp_summary, 
+       show_bgp_summary_cmd,
+       "show bgp summary",
+       SHOW_STR
+       BGP_STR
+       "Summary of BGP neighbor status\n")
+{
+  return bgp_show_summary_vty (vty, NULL, AFI_IP6, SAFI_UNICAST);
+}
+
+DEFUN (show_bgp_instance_summary,
+       show_bgp_instance_summary_cmd,
+       "show bgp view WORD summary",
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "View name\n"
+       "Summary of BGP neighbor status\n")
+{
+  return bgp_show_summary_vty (vty, argv[0], AFI_IP6, SAFI_UNICAST);
+}
+
+ALIAS (show_bgp_summary, 
+       show_bgp_ipv6_summary_cmd,
+       "show bgp ipv6 summary",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Summary of BGP neighbor status\n")
+
+ALIAS (show_bgp_instance_summary,
+       show_bgp_instance_ipv6_summary_cmd,
+       "show bgp view WORD ipv6 summary",
+       SHOW_STR
+       BGP_STR
+       "BGP view\n"
+       "View name\n"
+       "Address family\n"
+       "Summary of BGP neighbor status\n")
+
+/* old command */
+DEFUN (show_ipv6_bgp_summary, 
+       show_ipv6_bgp_summary_cmd,
+       "show ipv6 bgp summary",
+       SHOW_STR
+       IPV6_STR
+       BGP_STR
+       "Summary of BGP neighbor status\n")
+{
+  return bgp_show_summary_vty (vty, NULL, AFI_IP6, SAFI_UNICAST);
+}
+
+/* old command */
+DEFUN (show_ipv6_mbgp_summary, 
+       show_ipv6_mbgp_summary_cmd,
+       "show ipv6 mbgp summary",
+       SHOW_STR
+       IPV6_STR
+       MBGP_STR
+       "Summary of BGP neighbor status\n")
+{
+  return bgp_show_summary_vty (vty, NULL, AFI_IP6, SAFI_MULTICAST);
+}
+#endif /* HAVE_IPV6 */
+
+/* Show BGP peer's information. */
+enum show_type
+{
+  show_all,
+  show_peer
+};
+
+void
+bgp_show_peer_afi_orf_cap (struct vty *vty, struct peer *p,
+			   afi_t afi, safi_t safi,
+			   u_int16_t adv_smcap, u_int16_t adv_rmcap,
+			   u_int16_t rcv_smcap, u_int16_t rcv_rmcap)
+{
+  /* Send-Mode */
+  if (CHECK_FLAG (p->af_cap[afi][safi], adv_smcap)
+      || CHECK_FLAG (p->af_cap[afi][safi], rcv_smcap))
+    {
+      vty_out (vty, "      Send-mode: ");
+      if (CHECK_FLAG (p->af_cap[afi][safi], adv_smcap))
+	vty_out (vty, "advertised");
+      if (CHECK_FLAG (p->af_cap[afi][safi], rcv_smcap))
+	vty_out (vty, "%sreceived",
+		 CHECK_FLAG (p->af_cap[afi][safi], adv_smcap) ?
+		 ", " : "");
+      vty_out (vty, "%s", VTY_NEWLINE);
+    }
+
+  /* Receive-Mode */
+  if (CHECK_FLAG (p->af_cap[afi][safi], adv_rmcap)
+      || CHECK_FLAG (p->af_cap[afi][safi], rcv_rmcap))
+    {
+      vty_out (vty, "      Receive-mode: ");
+      if (CHECK_FLAG (p->af_cap[afi][safi], adv_rmcap))
+	vty_out (vty, "advertised");
+      if (CHECK_FLAG (p->af_cap[afi][safi], rcv_rmcap))
+	vty_out (vty, "%sreceived",
+		 CHECK_FLAG (p->af_cap[afi][safi], adv_rmcap) ?
+		 ", " : "");
+      vty_out (vty, "%s", VTY_NEWLINE);
+    }
+}
+
+void
+bgp_show_peer_afi (struct vty *vty, struct peer *p, afi_t afi, safi_t safi)
+{
+  struct bgp_filter *filter;
+  char orf_pfx_name[BUFSIZ];
+  int orf_pfx_count;
+
+  filter = &p->filter[afi][safi];
+
+  vty_out (vty, " For address family: %s %s%s",
+	   afi == AFI_IP6 ? "IPv6" :
+	   safi == SAFI_MPLS_VPN ? "VPNv4" : "IPv4",
+	   safi == SAFI_MULTICAST ? "Multicast" : "Unicast",
+	   VTY_NEWLINE);
+  if (p->af_group[afi][safi])
+    vty_out (vty, "  %s peer-group member%s", p->group->name, VTY_NEWLINE);
+
+  if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
+      || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
+      || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV)
+      || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
+      || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
+      || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
+    vty_out (vty, "  AF-dependant capabilities:%s", VTY_NEWLINE);
+
+  if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
+      || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
+      || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
+      || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
+    {
+      vty_out (vty, "    Outbound Route Filter (ORF) type (%d) Prefix-list:%s",
+	       ORF_TYPE_PREFIX, VTY_NEWLINE);
+      bgp_show_peer_afi_orf_cap (vty, p, afi, safi,
+				 PEER_CAP_ORF_PREFIX_SM_ADV,
+				 PEER_CAP_ORF_PREFIX_RM_ADV,
+				 PEER_CAP_ORF_PREFIX_SM_RCV,
+				 PEER_CAP_ORF_PREFIX_RM_RCV);
+    }
+  if (CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
+      || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV)
+      || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
+      || CHECK_FLAG (p->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV))
+    {
+      vty_out (vty, "    Outbound Route Filter (ORF) type (%d) Prefix-list:%s",
+	       ORF_TYPE_PREFIX_OLD, VTY_NEWLINE);
+      bgp_show_peer_afi_orf_cap (vty, p, afi, safi,
+				 PEER_CAP_ORF_PREFIX_SM_ADV,
+				 PEER_CAP_ORF_PREFIX_RM_ADV,
+				 PEER_CAP_ORF_PREFIX_SM_OLD_RCV,
+				 PEER_CAP_ORF_PREFIX_RM_OLD_RCV);
+    }
+
+  sprintf (orf_pfx_name, "%s.%d.%d", p->host, afi, safi);
+  orf_pfx_count =  prefix_bgp_show_prefix_list (NULL, afi, orf_pfx_name);
+
+  if (CHECK_FLAG (p->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND)
+      || orf_pfx_count)
+    {
+      vty_out (vty, "  Outbound Route Filter (ORF):");
+      if (CHECK_FLAG (p->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
+	  vty_out (vty, " sent;");
+      if (orf_pfx_count)
+	vty_out (vty, " received (%d entries)", orf_pfx_count);
+      vty_out (vty, "%s", VTY_NEWLINE);
+    }
+  if (CHECK_FLAG (p->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH))
+      vty_out (vty, "  First update is deferred until ORF or ROUTE-REFRESH is received%s", VTY_NEWLINE);
+
+  if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
+    vty_out (vty, "  Route-Reflector Client%s", VTY_NEWLINE);
+  if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
+    vty_out (vty, "  Route-Server Client%s", VTY_NEWLINE);
+  if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
+    vty_out (vty, "  Inbound soft reconfiguration allowed%s", VTY_NEWLINE);
+  if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS))
+    vty_out (vty, "  Private AS number removed from updates to this neighbor%s", VTY_NEWLINE);
+  if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF))
+    vty_out (vty, "  NEXT_HOP is always this router%s", VTY_NEWLINE);
+  if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED))
+    vty_out (vty, "  AS_PATH is propagated unchanged to this neighbor%s", VTY_NEWLINE);
+  if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED))
+    vty_out (vty, "  NEXT_HOP is propagated unchanged to this neighbor%s", VTY_NEWLINE);
+  if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
+    vty_out (vty, "  MED is propagated unchanged to this neighbor%s", VTY_NEWLINE);
+  if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
+      || CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY))
+    {
+      vty_out (vty, "  Community attribute sent to this neighbor");
+      if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
+	&& CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY))
+	vty_out (vty, " (both)%s", VTY_NEWLINE);
+      else if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY))
+	vty_out (vty, " (extended)%s", VTY_NEWLINE);
+      else 
+	vty_out (vty, " (standard)%s", VTY_NEWLINE);
+    }
+  if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
+    {
+      vty_out (vty, "  Default information originate,");
+
+      if (p->default_rmap[afi][safi].name)
+	vty_out (vty, " default route-map %s%s,",
+		 p->default_rmap[afi][safi].map ? "*" : "",
+		 p->default_rmap[afi][safi].name);
+      if (CHECK_FLAG (p->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE))
+	vty_out (vty, " default sent%s", VTY_NEWLINE);
+      else
+	vty_out (vty, " default not sent%s", VTY_NEWLINE);
+    }
+
+  if (filter->plist[FILTER_IN].name
+      || filter->dlist[FILTER_IN].name
+      || filter->aslist[FILTER_IN].name
+      || filter->map[FILTER_IN].name)
+    vty_out (vty, "  Inbound path policy configured%s", VTY_NEWLINE);
+  if (filter->plist[FILTER_OUT].name
+      || filter->dlist[FILTER_OUT].name
+      || filter->aslist[FILTER_OUT].name
+      || filter->map[FILTER_OUT].name
+      || filter->usmap.name)
+    vty_out (vty, "  Outbound path policy configured%s", VTY_NEWLINE);
+
+  /* prefix-list */
+  if (filter->plist[FILTER_IN].name)
+    vty_out (vty, "  Incoming update prefix filter list is %s%s%s",
+	     filter->plist[FILTER_IN].plist ? "*" : "",
+	     filter->plist[FILTER_IN].name,
+	     VTY_NEWLINE);
+  if (filter->plist[FILTER_OUT].name)
+    vty_out (vty, "  Outgoing update prefix filter list is %s%s%s",
+	     filter->plist[FILTER_OUT].plist ? "*" : "",
+	     filter->plist[FILTER_OUT].name,
+	     VTY_NEWLINE);
+
+  /* distribute-list */
+  if (filter->dlist[FILTER_IN].name)
+    vty_out (vty, "  Incoming update network filter list is %s%s%s",
+	     filter->dlist[FILTER_IN].alist ? "*" : "",
+	     filter->dlist[FILTER_IN].name,
+	     VTY_NEWLINE);
+  if (filter->dlist[FILTER_OUT].name)
+    vty_out (vty, "  Outgoing update network filter list is %s%s%s",
+	     filter->dlist[FILTER_OUT].alist ? "*" : "",
+	     filter->dlist[FILTER_OUT].name,
+	     VTY_NEWLINE);
+
+  /* filter-list. */
+  if (filter->aslist[FILTER_IN].name)
+    vty_out (vty, "  Incoming update AS path filter list is %s%s%s",
+	     filter->aslist[FILTER_IN].aslist ? "*" : "",
+	     filter->aslist[FILTER_IN].name,
+	     VTY_NEWLINE);
+  if (filter->aslist[FILTER_OUT].name)
+    vty_out (vty, "  Outgoing update AS path filter list is %s%s%s",
+	     filter->aslist[FILTER_OUT].aslist ? "*" : "",
+	     filter->aslist[FILTER_OUT].name,
+	     VTY_NEWLINE);
+
+  /* route-map. */
+  if (filter->map[FILTER_IN].name)
+    vty_out (vty, "  Route map for incoming advertisements is %s%s%s",
+	     filter->map[FILTER_IN].map ? "*" : "",
+	     filter->map[FILTER_IN].name,
+	     VTY_NEWLINE);
+  if (filter->map[FILTER_OUT].name)
+    vty_out (vty, "  Route map for outgoing advertisements is %s%s%s",
+	     filter->map[FILTER_OUT].map ? "*" : "",
+	     filter->map[FILTER_OUT].name,
+	     VTY_NEWLINE);
+
+  /* unsuppress-map */
+  if (filter->usmap.name)
+    vty_out (vty, "  Route map for selective unsuppress is %s%s%s",
+	     filter->usmap.map ? "*" : "",
+	     filter->usmap.name, VTY_NEWLINE);
+
+  /* Receive prefix count */
+  vty_out (vty, "  %ld accepted prefixes",
+	   p->pcount[afi][safi]);
+  /* Maximum prefix */
+  if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
+    {
+      vty_out (vty, ", maximum limit %ld%s",
+	       p->pmax[afi][safi],
+	       CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
+	       ? " (warning-only)" : "");
+    }
+  vty_out (vty, "%s", VTY_NEWLINE);
+
+  vty_out (vty, "%s", VTY_NEWLINE);
+}
+
+void
+bgp_show_peer (struct vty *vty, struct peer *p)
+{
+  struct bgp *bgp;
+  char buf1[BUFSIZ];
+  char timebuf[BGP_UPTIME_LEN];
+
+  bgp = p->bgp;
+
+  /* Configured IP address. */
+  vty_out (vty, "BGP neighbor is %s, ", p->host);
+  vty_out (vty, "remote AS %d, ", p->as);
+  vty_out (vty, "local AS %d%s, ",
+	   p->change_local_as ? p->change_local_as : p->local_as,
+	   CHECK_FLAG (p->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
+	   " no-prepend" : "");
+  vty_out (vty, "%s link%s",
+	   p->as == p->local_as ? "internal" : "external",
+	   VTY_NEWLINE);
+
+  /* Description. */
+  if (p->desc)
+    vty_out (vty, " Description: %s%s", p->desc, VTY_NEWLINE);
+  
+  /* Peer-group */
+  if (p->group)
+    vty_out (vty, " Member of peer-group %s for session parameters%s",
+	     p->group->name, VTY_NEWLINE);
+
+  /* Administrative shutdown. */
+  if (CHECK_FLAG (p->flags, PEER_FLAG_SHUTDOWN))
+    vty_out (vty, " Administratively shut down%s", VTY_NEWLINE);
+
+  /* BGP Version. */
+  vty_out (vty, "  BGP version 4");
+  if (p->version == BGP_VERSION_MP_4_DRAFT_00)
+    vty_out (vty, "(with draft-00 verion of multiporotocol extension)");
+  vty_out (vty, ", remote router ID %s%s", 
+	   inet_ntop (AF_INET, &p->remote_id, buf1, BUFSIZ),
+	   VTY_NEWLINE);
+
+  /* Confederation */
+  if (bgp_confederation_peers_check (bgp, p->as)) 
+    vty_out (vty, "  Neighbor under common administration%s", VTY_NEWLINE);
+  
+  /* Status. */
+  vty_out (vty, "  BGP state = %s",  
+	   LOOKUP (bgp_status_msg, p->status));
+  if (p->status == Established) 
+    vty_out (vty, ", up for %8s", 
+	     peer_uptime (p->uptime, timebuf, BGP_UPTIME_LEN));
+  vty_out (vty, "%s", VTY_NEWLINE);
+  
+  /* read timer */
+  vty_out (vty, "  Last read %s", peer_uptime (p->readtime, timebuf, BGP_UPTIME_LEN));
+
+  /* Configured timer values. */
+  vty_out (vty, ", hold time is %d, keepalive interval is %d seconds%s",
+	   p->v_holdtime, p->v_keepalive, VTY_NEWLINE);
+  if (CHECK_FLAG (p->config, PEER_CONFIG_TIMER))
+    {
+      vty_out (vty, "  Configured hold time is %d", p->holdtime);
+      vty_out (vty, ", keepalive interval is %d seconds%s",
+	       p->keepalive, VTY_NEWLINE);
+    }
+  
+  /* Capability. */
+  if (p->status == Established) 
+    {
+      if (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_ADV)
+	  || CHECK_FLAG (p->cap, PEER_CAP_REFRESH_NEW_RCV)
+	  || CHECK_FLAG (p->cap, PEER_CAP_REFRESH_OLD_RCV)
+	  || CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_ADV)
+	  || CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_RCV)
+	  || p->afc_adv[AFI_IP][SAFI_UNICAST]
+	  || p->afc_recv[AFI_IP][SAFI_UNICAST]
+	  || p->afc_adv[AFI_IP][SAFI_MULTICAST]
+	  || p->afc_recv[AFI_IP][SAFI_MULTICAST]
+#ifdef HAVE_IPV6
+	  || p->afc_adv[AFI_IP6][SAFI_UNICAST]
+	  || p->afc_recv[AFI_IP6][SAFI_UNICAST]
+	  || p->afc_adv[AFI_IP6][SAFI_MULTICAST]
+	  || p->afc_recv[AFI_IP6][SAFI_MULTICAST]
+#endif /* HAVE_IPV6 */
+	  || p->afc_adv[AFI_IP][SAFI_MPLS_VPN]
+	  || p->afc_recv[AFI_IP][SAFI_MPLS_VPN])
+	{
+	  vty_out (vty, "  Neighbor capabilities:%s", VTY_NEWLINE);
+
+	  /* Dynamic */
+	  if (CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_RCV)
+	      || CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_ADV))
+	    {
+	      vty_out (vty, "    Dynamic:");
+	      if (CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_ADV))
+		vty_out (vty, " advertised");
+	      if (CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_RCV))
+		{
+		  if (CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_ADV))
+		    vty_out (vty, " and");
+		  vty_out (vty, " received");
+		}
+	      vty_out (vty, "%s", VTY_NEWLINE);
+	    }
+
+	  /* Route Refresh */
+	  if (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_ADV)
+	      || CHECK_FLAG (p->cap, PEER_CAP_REFRESH_NEW_RCV)
+	      || CHECK_FLAG (p->cap, PEER_CAP_REFRESH_OLD_RCV))
+	    {
+	      vty_out (vty, "    Route refresh:");
+ 	      if (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_ADV))
+		vty_out (vty, " advertised");
+	      if (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_NEW_RCV)
+		  || CHECK_FLAG (p->cap, PEER_CAP_REFRESH_OLD_RCV))
+		{
+		  if (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_ADV))
+		    vty_out (vty, " and");
+		  vty_out (vty, " received");
+		  if (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_NEW_RCV)
+		      && CHECK_FLAG (p->cap, PEER_CAP_REFRESH_OLD_RCV))
+		    vty_out (vty, " (old and new)");
+		  else if (CHECK_FLAG (p->cap, PEER_CAP_REFRESH_OLD_RCV))
+		    vty_out (vty, " (old)");
+		  else 
+		    vty_out (vty, " (new)");
+		}
+	      vty_out (vty, "%s", VTY_NEWLINE);
+	    }
+
+	  /* IPv4 */
+	  if (p->afc_adv[AFI_IP][SAFI_UNICAST]
+	      || p->afc_recv[AFI_IP][SAFI_UNICAST]) 
+	    {
+	      vty_out (vty, "    Address family IPv4 Unicast:");
+	      if (p->afc_adv[AFI_IP][SAFI_UNICAST]) 
+		vty_out (vty, " advertised");
+	      if (p->afc_recv[AFI_IP][SAFI_UNICAST])
+		{
+		  if (p->afc_adv[AFI_IP][SAFI_UNICAST])
+		    vty_out (vty, " and");
+		  vty_out (vty, " received");
+		}
+	      vty_out (vty, "%s", VTY_NEWLINE);
+	    }
+	  if (p->afc_adv[AFI_IP][SAFI_MULTICAST] || p->afc_recv[AFI_IP][SAFI_MULTICAST]) 
+	    {
+	      vty_out (vty, "    Address family IPv4 Multicast:");
+	      if (p->afc_adv[AFI_IP][SAFI_MULTICAST]) 
+		vty_out (vty, " advertised");
+	      if (p->afc_recv[AFI_IP][SAFI_MULTICAST])
+		{
+		  if (p->afc_adv[AFI_IP][SAFI_MULTICAST])
+		    vty_out (vty, " and");
+		  vty_out (vty, " received");
+		}
+	      vty_out (vty, "%s", VTY_NEWLINE);
+	    }
+	  if (p->afc_adv[AFI_IP][SAFI_MPLS_VPN] || p->afc_recv[AFI_IP][SAFI_MPLS_VPN]) 
+	    {
+	      vty_out (vty, "    Address family VPNv4 Unicast:");
+	      if (p->afc_adv[AFI_IP][SAFI_MPLS_VPN]) 
+		vty_out (vty, " advertised");
+	      if (p->afc_recv[AFI_IP][SAFI_MPLS_VPN])
+		{
+		  if (p->afc_adv[AFI_IP][SAFI_MPLS_VPN])
+		    vty_out (vty, " and");
+		  vty_out (vty, " received");
+		}
+	      vty_out (vty, "%s", VTY_NEWLINE);
+	    }
+	  /* IPv6 */
+#ifdef HAVE_IPV6
+	  if (p->afc_adv[AFI_IP6][SAFI_UNICAST] || p->afc_recv[AFI_IP6][SAFI_UNICAST]) 
+	    {
+	      vty_out (vty, "    Address family IPv6 Unicast:");
+	      if (p->afc_adv[AFI_IP6][SAFI_UNICAST]) 
+		vty_out (vty, " advertised");
+	      if (p->afc_recv[AFI_IP6][SAFI_UNICAST])
+		{
+		  if (p->afc_adv[AFI_IP6][SAFI_UNICAST])
+		    vty_out (vty, " and");
+		  vty_out (vty, " received");
+		}
+	      vty_out (vty, "%s", VTY_NEWLINE);
+	    }
+	  if (p->afc_adv[AFI_IP6][SAFI_MULTICAST] || p->afc_recv[AFI_IP6][SAFI_MULTICAST]) 
+	    {
+	      vty_out (vty, "    Address family IPv6 Multicast:");
+	      if (p->afc_adv[AFI_IP6][SAFI_MULTICAST]) 
+		vty_out (vty, " advertised");
+	      if (p->afc_recv[AFI_IP6][SAFI_MULTICAST])
+		{
+		  if (p->afc_adv[AFI_IP6][SAFI_MULTICAST])
+		    vty_out (vty, " and");
+		  vty_out (vty, " received");
+		}
+	      vty_out (vty, "%s", VTY_NEWLINE);
+	    }
+#endif /* HAVE_IPV6 */
+	}
+    }
+
+  /* Packet counts. */
+  vty_out(vty, "  Received %d messages, %d notifications, %d in queue%s",
+	  p->open_in + p->update_in + p->keepalive_in + p->refresh_in
+	  + p->dynamic_cap_in, p->notify_in, 0, VTY_NEWLINE);
+  vty_out(vty, "  Sent %d messages, %d notifications, %ld in queue%s",
+	  p->open_out + p->update_out + p->keepalive_out + p->refresh_out
+	  + p->dynamic_cap_out, p->notify_out, p->obuf->count, VTY_NEWLINE);
+  vty_out(vty, "  Route refresh request: received %d, sent %d%s",
+	  p->refresh_in, p->refresh_out, VTY_NEWLINE);
+
+  /* advertisement-interval */
+  vty_out (vty, "  Minimum time between advertisement runs is %d seconds%s",
+	   p->v_routeadv, VTY_NEWLINE);
+
+  /* Update-source. */
+  if (p->update_if || p->update_source)
+    {
+      vty_out (vty, "  Update source is ");
+      if (p->update_if)
+	vty_out (vty, "%s", p->update_if);
+      else if (p->update_source)
+	vty_out (vty, "%s",
+		 sockunion2str (p->update_source, buf1, SU_ADDRSTRLEN));
+      vty_out (vty, "%s", VTY_NEWLINE);
+    }
+
+  /* Default weight */
+  if (CHECK_FLAG (p->config, PEER_CONFIG_WEIGHT))
+    vty_out (vty, "  Default weight %d%s", p->weight,
+	     VTY_NEWLINE);
+
+  vty_out (vty, "%s", VTY_NEWLINE);
+
+  /* Address Family Information */
+  if (p->afc[AFI_IP][SAFI_UNICAST])
+    bgp_show_peer_afi (vty, p, AFI_IP, SAFI_UNICAST);
+  if (p->afc[AFI_IP][SAFI_MULTICAST])
+    bgp_show_peer_afi (vty, p, AFI_IP, SAFI_MULTICAST);
+  if (p->afc[AFI_IP][SAFI_MPLS_VPN])
+    bgp_show_peer_afi (vty, p, AFI_IP, SAFI_MPLS_VPN);
+#ifdef HAVE_IPV6
+  if (p->afc[AFI_IP6][SAFI_UNICAST])
+    bgp_show_peer_afi (vty, p, AFI_IP6, SAFI_UNICAST);
+  if (p->afc[AFI_IP6][SAFI_MULTICAST])
+    bgp_show_peer_afi (vty, p, AFI_IP6, SAFI_MULTICAST);
+#endif /* HAVE_IPV6 */
+
+  vty_out (vty, "  Connections established %d; dropped %d%s",
+	   p->established, p->dropped,
+	   VTY_NEWLINE);
+
+  if (CHECK_FLAG (p->sflags, PEER_STATUS_PREFIX_OVERFLOW))
+    {
+      vty_out (vty, "  Peer had exceeded the max. no. of prefixes configured.%s", VTY_NEWLINE);
+      vty_out (vty, "  Reduce the no. of prefix and clear ip bgp %s to restore peering%s",
+	       p->host, VTY_NEWLINE);
+    }
+
+  /* EBGP Multihop */
+  if (peer_sort (p) != BGP_PEER_IBGP && p->ttl > 1)
+    vty_out (vty, "  External BGP neighbor may be up to %d hops away.%s",
+	     p->ttl, VTY_NEWLINE);
+
+  /* Local address. */
+  if (p->su_local)
+    {
+      vty_out (vty, "Local host: %s, Local port: %d%s%s",
+	       sockunion2str (p->su_local, buf1, SU_ADDRSTRLEN),
+	       ntohs (p->su_local->sin.sin_port),
+	       CHECK_FLAG (p->flags, PEER_FLAG_PASSIVE) ?
+	       ", passive-mode" : "", 
+	       VTY_NEWLINE);
+    }
+      
+  /* Remote address. */
+  if (p->su_remote)
+    {
+      vty_out (vty, "Foreign host: %s, Foreign port: %d%s",
+	       sockunion2str (p->su_remote, buf1, SU_ADDRSTRLEN),
+	       ntohs (p->su_remote->sin.sin_port),
+	       VTY_NEWLINE);
+    }
+
+  /* Nexthop display. */
+  if (p->su_local)
+    {
+      vty_out (vty, "Nexthop: %s%s", 
+	       inet_ntop (AF_INET, &p->nexthop.v4, buf1, BUFSIZ),
+	       VTY_NEWLINE);
+#ifdef HAVE_IPV6
+      vty_out (vty, "Nexthop global: %s%s", 
+	       inet_ntop (AF_INET6, &p->nexthop.v6_global, buf1, BUFSIZ),
+	       VTY_NEWLINE);
+      vty_out (vty, "Nexthop local: %s%s",
+	       inet_ntop (AF_INET6, &p->nexthop.v6_local, buf1, BUFSIZ),
+	       VTY_NEWLINE);
+      vty_out (vty, "BGP connection: %s%s",
+	       p->shared_network ? "shared network" : "non shared network",
+	       VTY_NEWLINE);
+#endif /* HAVE_IPV6 */
+    }
+
+  /* Timer information. */
+  if (p->t_start)
+    vty_out (vty, "Next start timer due in %ld seconds%s",
+	     thread_timer_remain_second (p->t_start), VTY_NEWLINE);
+  if (p->t_connect)
+    vty_out (vty, "Next connect timer due in %ld seconds%s",
+	     thread_timer_remain_second (p->t_connect), VTY_NEWLINE);
+  
+  vty_out (vty, "Read thread: %s  Write thread: %s%s", 
+	   p->t_read ? "on" : "off",
+	   p->t_write ? "on" : "off",
+	   VTY_NEWLINE);
+
+  if (p->notify.code == BGP_NOTIFY_OPEN_ERR
+      && p->notify.subcode == BGP_NOTIFY_OPEN_UNSUP_CAPBL)
+    bgp_capability_vty_out (vty, p);
+ 
+  vty_out (vty, "%s", VTY_NEWLINE);
+}
+
+int
+bgp_show_neighbor (struct vty *vty, struct bgp *bgp,
+		   enum show_type type, union sockunion *su)
+{
+  struct listnode *nn;
+  struct peer *peer;
+  int find = 0;
+
+  LIST_LOOP (bgp->peer, peer, nn)
+    {
+      switch (type)
+	{
+	case show_all:
+	  bgp_show_peer (vty, peer);
+	  break;
+	case show_peer:
+	  if (sockunion_same (&peer->su, su))
+	    {
+	      find = 1;
+	      bgp_show_peer (vty, peer);
+	    }
+	  break;
+	}
+    }
+
+  if (type == show_peer && ! find)
+    vty_out (vty, "%% No such neighbor%s", VTY_NEWLINE);
+  
+  return CMD_SUCCESS;
+}
+
+int 
+bgp_show_neighbor_vty (struct vty *vty, char *name, enum show_type type,
+		       char *ip_str)
+{
+  int ret;
+  struct bgp *bgp;
+  union sockunion su;
+
+  if (ip_str)
+    {
+      ret = str2sockunion (ip_str, &su);
+      if (ret < 0)
+        {
+          vty_out (vty, "%% Malformed address: %s%s", ip_str, VTY_NEWLINE);
+          return CMD_WARNING;
+        }
+    }
+
+  if (name)
+    {
+      bgp = bgp_lookup_by_name (name);
+      
+      if (! bgp)
+        {
+          vty_out (vty, "%% No such BGP instance exist%s", VTY_NEWLINE); 
+          return CMD_WARNING;
+        }
+
+      bgp_show_neighbor (vty, bgp, type, &su);
+
+      return CMD_SUCCESS;
+    }
+
+  bgp = bgp_get_default ();
+
+  if (bgp)
+    bgp_show_neighbor (vty, bgp, type, &su);
+
+  return CMD_SUCCESS;
+}
+
+/* "show ip bgp neighbors" commands.  */
+DEFUN (show_ip_bgp_neighbors,
+       show_ip_bgp_neighbors_cmd,
+       "show ip bgp neighbors",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Detailed information on TCP and BGP neighbor connections\n")
+{
+  return bgp_show_neighbor_vty (vty, NULL, show_all, NULL);
+}
+
+ALIAS (show_ip_bgp_neighbors,
+       show_ip_bgp_ipv4_neighbors_cmd,
+       "show ip bgp ipv4 (unicast|multicast) neighbors",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Detailed information on TCP and BGP neighbor connections\n")
+
+ALIAS (show_ip_bgp_neighbors,
+       show_ip_bgp_vpnv4_all_neighbors_cmd,
+       "show ip bgp vpnv4 all neighbors",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display VPNv4 NLRI specific information\n"
+       "Display information about all VPNv4 NLRIs\n"
+       "Detailed information on TCP and BGP neighbor connections\n")
+
+ALIAS (show_ip_bgp_neighbors,
+       show_ip_bgp_vpnv4_rd_neighbors_cmd,
+       "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn neighbors",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display VPNv4 NLRI specific information\n"
+       "Display information for a route distinguisher\n"
+       "VPN Route Distinguisher\n"
+       "Detailed information on TCP and BGP neighbor connections\n")
+
+ALIAS (show_ip_bgp_neighbors,
+       show_bgp_neighbors_cmd,
+       "show bgp neighbors",
+       SHOW_STR
+       BGP_STR
+       "Detailed information on TCP and BGP neighbor connections\n")
+
+ALIAS (show_ip_bgp_neighbors,
+       show_bgp_ipv6_neighbors_cmd,
+       "show bgp ipv6 neighbors",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Detailed information on TCP and BGP neighbor connections\n")
+
+DEFUN (show_ip_bgp_neighbors_peer,
+       show_ip_bgp_neighbors_peer_cmd,
+       "show ip bgp neighbors (A.B.C.D|X:X::X:X)",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n")
+{
+  return bgp_show_neighbor_vty (vty, NULL, show_peer, argv[argc - 1]);
+}
+
+ALIAS (show_ip_bgp_neighbors_peer,
+       show_ip_bgp_ipv4_neighbors_peer_cmd,
+       "show ip bgp ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X)",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n")
+
+ALIAS (show_ip_bgp_neighbors_peer,
+       show_ip_bgp_vpnv4_all_neighbors_peer_cmd,
+       "show ip bgp vpnv4 all neighbors A.B.C.D",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display VPNv4 NLRI specific information\n"
+       "Display information about all VPNv4 NLRIs\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n")
+
+ALIAS (show_ip_bgp_neighbors_peer,
+       show_ip_bgp_vpnv4_rd_neighbors_peer_cmd,
+       "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn neighbors A.B.C.D",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Display VPNv4 NLRI specific information\n"
+       "Display information about all VPNv4 NLRIs\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n")
+
+ALIAS (show_ip_bgp_neighbors_peer,
+       show_bgp_neighbors_peer_cmd,
+       "show bgp neighbors (A.B.C.D|X:X::X:X)",
+       SHOW_STR
+       BGP_STR
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n")
+
+ALIAS (show_ip_bgp_neighbors_peer,
+       show_bgp_ipv6_neighbors_peer_cmd,
+       "show bgp ipv6 neighbors (A.B.C.D|X:X::X:X)",
+       SHOW_STR
+       BGP_STR
+       "Address family\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n")
+
+DEFUN (show_ip_bgp_instance_neighbors,
+       show_ip_bgp_instance_neighbors_cmd,
+       "show ip bgp view WORD neighbors",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "BGP view\n"
+       "View name\n"
+       "Detailed information on TCP and BGP neighbor connections\n")
+{
+  return bgp_show_neighbor_vty (vty, argv[0], show_all, NULL);
+}
+
+DEFUN (show_ip_bgp_instance_neighbors_peer,
+       show_ip_bgp_instance_neighbors_peer_cmd,
+       "show ip bgp view WORD neighbors (A.B.C.D|X:X::X:X)",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "BGP view\n"
+       "View name\n"
+       "Detailed information on TCP and BGP neighbor connections\n"
+       "Neighbor to display information about\n"
+       "Neighbor to display information about\n")
+{
+  return bgp_show_neighbor_vty (vty, argv[0], show_peer, argv[1]);
+}
+
+/* Show BGP's AS paths internal data.  There are both `show ip bgp
+   paths' and `show ip mbgp paths'.  Those functions results are the
+   same.*/
+DEFUN (show_ip_bgp_paths, 
+       show_ip_bgp_paths_cmd,
+       "show ip bgp paths",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Path information\n")
+{
+  vty_out (vty, "Address Refcnt Path%s", VTY_NEWLINE);
+  aspath_print_all_vty (vty);
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_bgp_ipv4_paths, 
+       show_ip_bgp_ipv4_paths_cmd,
+       "show ip bgp ipv4 (unicast|multicast) paths",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "Address family\n"
+       "Address Family modifier\n"
+       "Address Family modifier\n"
+       "Path information\n")
+{
+  vty_out (vty, "Address Refcnt Path\r\n");
+  aspath_print_all_vty (vty);
+
+  return CMD_SUCCESS;
+}
+
+#include "hash.h"
+
+void
+community_show_all_iterator (struct hash_backet *backet, struct vty *vty)
+{
+  struct community *com;
+
+  com = (struct community *) backet->data;
+  vty_out (vty, "[%p] (%ld) %s%s", backet, com->refcnt,
+	   community_str (com), VTY_NEWLINE);
+}
+
+/* Show BGP's community internal data. */
+DEFUN (show_ip_bgp_community_info, 
+       show_ip_bgp_community_info_cmd,
+       "show ip bgp community-info",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "List all bgp community information\n")
+{
+  vty_out (vty, "Address Refcnt Community%s", VTY_NEWLINE);
+
+  hash_iterate (community_hash (), 
+		(void (*) (struct hash_backet *, void *))
+		community_show_all_iterator,
+		vty);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_bgp_attr_info, 
+       show_ip_bgp_attr_info_cmd,
+       "show ip bgp attribute-info",
+       SHOW_STR
+       IP_STR
+       BGP_STR
+       "List all bgp attribute information\n")
+{
+  attr_show_all (vty);
+  return CMD_SUCCESS;
+}
+
+/* Redistribute VTY commands.  */
+
+/* Utility function to convert user input route type string to route
+   type.  */
+static int
+bgp_str2route_type (int afi, char *str)
+{
+  if (! str)
+    return 0;
+
+  if (afi == AFI_IP)
+    {
+      if (strncmp (str, "k", 1) == 0)
+	return ZEBRA_ROUTE_KERNEL;
+      else if (strncmp (str, "c", 1) == 0)
+	return ZEBRA_ROUTE_CONNECT;
+      else if (strncmp (str, "s", 1) == 0)
+	return ZEBRA_ROUTE_STATIC;
+      else if (strncmp (str, "r", 1) == 0)
+	return ZEBRA_ROUTE_RIP;
+      else if (strncmp (str, "o", 1) == 0)
+	return ZEBRA_ROUTE_OSPF;
+    }
+  if (afi == AFI_IP6)
+    {
+      if (strncmp (str, "k", 1) == 0)
+	return ZEBRA_ROUTE_KERNEL;
+      else if (strncmp (str, "c", 1) == 0)
+	return ZEBRA_ROUTE_CONNECT;
+      else if (strncmp (str, "s", 1) == 0)
+	return ZEBRA_ROUTE_STATIC;
+      else if (strncmp (str, "r", 1) == 0)
+	return ZEBRA_ROUTE_RIPNG;
+      else if (strncmp (str, "o", 1) == 0)
+	return ZEBRA_ROUTE_OSPF6;
+    }
+  return 0;
+}
+
+DEFUN (bgp_redistribute_ipv4,
+       bgp_redistribute_ipv4_cmd,
+       "redistribute (connected|kernel|ospf|rip|static)",
+       "Redistribute information from another routing protocol\n"
+       "Connected\n"
+       "Kernel routes\n"
+       "Open Shurtest Path First (OSPF)\n"
+       "Routing Information Protocol (RIP)\n"
+       "Static routes\n")
+{
+  int type;
+
+  type = bgp_str2route_type (AFI_IP, argv[0]);
+  if (! type)
+    {
+      vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  return bgp_redistribute_set (vty->index, AFI_IP, type);
+}
+
+DEFUN (bgp_redistribute_ipv4_rmap,
+       bgp_redistribute_ipv4_rmap_cmd,
+       "redistribute (connected|kernel|ospf|rip|static) route-map WORD",
+       "Redistribute information from another routing protocol\n"
+       "Connected\n"
+       "Kernel routes\n"
+       "Open Shurtest Path First (OSPF)\n"
+       "Routing Information Protocol (RIP)\n"
+       "Static routes\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n")
+{
+  int type;
+
+  type = bgp_str2route_type (AFI_IP, argv[0]);
+  if (! type)
+    {
+      vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  bgp_redistribute_rmap_set (vty->index, AFI_IP, type, argv[1]);
+  return bgp_redistribute_set (vty->index, AFI_IP, type);
+}
+
+DEFUN (bgp_redistribute_ipv4_metric,
+       bgp_redistribute_ipv4_metric_cmd,
+       "redistribute (connected|kernel|ospf|rip|static) metric <0-4294967295>",
+       "Redistribute information from another routing protocol\n"
+       "Connected\n"
+       "Kernel routes\n"
+       "Open Shurtest Path First (OSPF)\n"
+       "Routing Information Protocol (RIP)\n"
+       "Static routes\n"
+       "Metric for redistributed routes\n"
+       "Default metric\n")
+{
+  int type;
+  u_int32_t metric;
+
+  type = bgp_str2route_type (AFI_IP, argv[0]);
+  if (! type)
+    {
+      vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  VTY_GET_INTEGER ("metric", metric, argv[1]);
+
+  bgp_redistribute_metric_set (vty->index, AFI_IP, type, metric);
+  return bgp_redistribute_set (vty->index, AFI_IP, type);
+}
+
+DEFUN (bgp_redistribute_ipv4_rmap_metric,
+       bgp_redistribute_ipv4_rmap_metric_cmd,
+       "redistribute (connected|kernel|ospf|rip|static) route-map WORD metric <0-4294967295>",
+       "Redistribute information from another routing protocol\n"
+       "Connected\n"
+       "Kernel routes\n"
+       "Open Shurtest Path First (OSPF)\n"
+       "Routing Information Protocol (RIP)\n"
+       "Static routes\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n"
+       "Metric for redistributed routes\n"
+       "Default metric\n")
+{
+  int type;
+  u_int32_t metric;
+
+  type = bgp_str2route_type (AFI_IP, argv[0]);
+  if (! type)
+    {
+      vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  VTY_GET_INTEGER ("metric", metric, argv[2]);
+
+  bgp_redistribute_rmap_set (vty->index, AFI_IP, type, argv[1]);
+  bgp_redistribute_metric_set (vty->index, AFI_IP, type, metric);
+  return bgp_redistribute_set (vty->index, AFI_IP, type);
+}
+
+DEFUN (bgp_redistribute_ipv4_metric_rmap,
+       bgp_redistribute_ipv4_metric_rmap_cmd,
+       "redistribute (connected|kernel|ospf|rip|static) metric <0-4294967295> route-map WORD",
+       "Redistribute information from another routing protocol\n"
+       "Connected\n"
+       "Kernel routes\n"
+       "Open Shurtest Path First (OSPF)\n"
+       "Routing Information Protocol (RIP)\n"
+       "Static routes\n"
+       "Metric for redistributed routes\n"
+       "Default metric\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n")
+{
+  int type;
+  u_int32_t metric;
+
+  type = bgp_str2route_type (AFI_IP, argv[0]);
+  if (! type)
+    {
+      vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  VTY_GET_INTEGER ("metric", metric, argv[1]);
+
+  bgp_redistribute_metric_set (vty->index, AFI_IP, type, metric);
+  bgp_redistribute_rmap_set (vty->index, AFI_IP, type, argv[2]);
+  return bgp_redistribute_set (vty->index, AFI_IP, type);
+}
+
+DEFUN (no_bgp_redistribute_ipv4,
+       no_bgp_redistribute_ipv4_cmd,
+       "no redistribute (connected|kernel|ospf|rip|static)",
+       NO_STR
+       "Redistribute information from another routing protocol\n"
+       "Connected\n"
+       "Kernel routes\n"
+       "Open Shurtest Path First (OSPF)\n"
+       "Routing Information Protocol (RIP)\n"
+       "Static routes\n")
+{
+  int type;
+
+  type = bgp_str2route_type (AFI_IP, argv[0]);
+  if (! type)
+    {
+      vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_redistribute_unset (vty->index, AFI_IP, type);
+}
+
+DEFUN (no_bgp_redistribute_ipv4_rmap,
+       no_bgp_redistribute_ipv4_rmap_cmd,
+       "no redistribute (connected|kernel|ospf|rip|static) route-map WORD",
+       NO_STR
+       "Redistribute information from another routing protocol\n"
+       "Connected\n"
+       "Kernel routes\n"
+       "Open Shurtest Path First (OSPF)\n"
+       "Routing Information Protocol (RIP)\n"
+       "Static routes\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n")
+{
+  int type;
+
+  type = bgp_str2route_type (AFI_IP, argv[0]);
+  if (! type)
+    {
+      vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  bgp_redistribute_routemap_unset (vty->index, AFI_IP, type);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_redistribute_ipv4_metric,
+       no_bgp_redistribute_ipv4_metric_cmd,
+       "no redistribute (connected|kernel|ospf|rip|static) metric <0-4294967295>",
+       NO_STR
+       "Redistribute information from another routing protocol\n"
+       "Connected\n"
+       "Kernel routes\n"
+       "Open Shurtest Path First (OSPF)\n"
+       "Routing Information Protocol (RIP)\n"
+       "Static routes\n"
+       "Metric for redistributed routes\n"
+       "Default metric\n")
+{
+  int type;
+
+  type = bgp_str2route_type (AFI_IP, argv[0]);
+  if (! type)
+    {
+      vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  bgp_redistribute_metric_unset (vty->index, AFI_IP, type);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_redistribute_ipv4_rmap_metric,
+       no_bgp_redistribute_ipv4_rmap_metric_cmd,
+       "no redistribute (connected|kernel|ospf|rip|static) route-map WORD metric <0-4294967295>",
+       NO_STR
+       "Redistribute information from another routing protocol\n"
+       "Connected\n"
+       "Kernel routes\n"
+       "Open Shurtest Path First (OSPF)\n"
+       "Routing Information Protocol (RIP)\n"
+       "Static routes\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n"
+       "Metric for redistributed routes\n"
+       "Default metric\n")
+{
+  int type;
+
+  type = bgp_str2route_type (AFI_IP, argv[0]);
+  if (! type)
+    {
+      vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  bgp_redistribute_metric_unset (vty->index, AFI_IP, type);
+  bgp_redistribute_routemap_unset (vty->index, AFI_IP, type);
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_bgp_redistribute_ipv4_rmap_metric,
+       no_bgp_redistribute_ipv4_metric_rmap_cmd,
+       "no redistribute (connected|kernel|ospf|rip|static) metric <0-4294967295> route-map WORD",
+       NO_STR
+       "Redistribute information from another routing protocol\n"
+       "Connected\n"
+       "Kernel routes\n"
+       "Open Shurtest Path First (OSPF)\n"
+       "Routing Information Protocol (RIP)\n"
+       "Static routes\n"
+       "Metric for redistributed routes\n"
+       "Default metric\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n")
+
+#ifdef HAVE_IPV6
+DEFUN (bgp_redistribute_ipv6,
+       bgp_redistribute_ipv6_cmd,
+       "redistribute (connected|kernel|ospf6|ripng|static)",
+       "Redistribute information from another routing protocol\n"
+       "Connected\n"
+       "Kernel routes\n"
+       "Open Shurtest Path First (OSPFv3)\n"
+       "Routing Information Protocol (RIPng)\n"
+       "Static routes\n")
+{
+  int type;
+
+  type = bgp_str2route_type (AFI_IP6, argv[0]);
+  if (! type)
+    {
+      vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_redistribute_set (vty->index, AFI_IP6, type);
+}
+
+DEFUN (bgp_redistribute_ipv6_rmap,
+       bgp_redistribute_ipv6_rmap_cmd,
+       "redistribute (connected|kernel|ospf6|ripng|static) route-map WORD",
+       "Redistribute information from another routing protocol\n"
+       "Connected\n"
+       "Kernel routes\n"
+       "Open Shurtest Path First (OSPFv3)\n"
+       "Routing Information Protocol (RIPng)\n"
+       "Static routes\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n")
+{
+  int type;
+
+  type = bgp_str2route_type (AFI_IP6, argv[0]);
+  if (! type)
+    {
+      vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  bgp_redistribute_rmap_set (vty->index, AFI_IP6, type, argv[1]);
+  return bgp_redistribute_set (vty->index, AFI_IP6, type);
+}
+
+DEFUN (bgp_redistribute_ipv6_metric,
+       bgp_redistribute_ipv6_metric_cmd,
+       "redistribute (connected|kernel|ospf6|ripng|static) metric <0-4294967295>",
+       "Redistribute information from another routing protocol\n"
+       "Connected\n"
+       "Kernel routes\n"
+       "Open Shurtest Path First (OSPFv3)\n"
+       "Routing Information Protocol (RIPng)\n"
+       "Static routes\n"
+       "Metric for redistributed routes\n"
+       "Default metric\n")
+{
+  int type;
+  u_int32_t metric;
+
+  type = bgp_str2route_type (AFI_IP6, argv[0]);
+  if (! type)
+    {
+      vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  VTY_GET_INTEGER ("metric", metric, argv[1]);
+
+  bgp_redistribute_metric_set (vty->index, AFI_IP6, type, metric);
+  return bgp_redistribute_set (vty->index, AFI_IP6, type);
+}
+
+DEFUN (bgp_redistribute_ipv6_rmap_metric,
+       bgp_redistribute_ipv6_rmap_metric_cmd,
+       "redistribute (connected|kernel|ospf6|ripng|static) route-map WORD metric <0-4294967295>",
+       "Redistribute information from another routing protocol\n"
+       "Connected\n"
+       "Kernel routes\n"
+       "Open Shurtest Path First (OSPFv3)\n"
+       "Routing Information Protocol (RIPng)\n"
+       "Static routes\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n"
+       "Metric for redistributed routes\n"
+       "Default metric\n")
+{
+  int type;
+  u_int32_t metric;
+
+  type = bgp_str2route_type (AFI_IP6, argv[0]);
+  if (! type)
+    {
+      vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  VTY_GET_INTEGER ("metric", metric, argv[2]);
+
+  bgp_redistribute_rmap_set (vty->index, AFI_IP6, type, argv[1]);
+  bgp_redistribute_metric_set (vty->index, AFI_IP6, type, metric);
+  return bgp_redistribute_set (vty->index, AFI_IP6, type);
+}
+
+DEFUN (bgp_redistribute_ipv6_metric_rmap,
+       bgp_redistribute_ipv6_metric_rmap_cmd,
+       "redistribute (connected|kernel|ospf6|ripng|static) metric <0-4294967295> route-map WORD",
+       "Redistribute information from another routing protocol\n"
+       "Connected\n"
+       "Kernel routes\n"
+       "Open Shurtest Path First (OSPFv3)\n"
+       "Routing Information Protocol (RIPng)\n"
+       "Static routes\n"
+       "Metric for redistributed routes\n"
+       "Default metric\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n")
+{
+  int type;
+  u_int32_t metric;
+
+  type = bgp_str2route_type (AFI_IP6, argv[0]);
+  if (! type)
+    {
+      vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+  VTY_GET_INTEGER ("metric", metric, argv[1]);
+
+  bgp_redistribute_metric_set (vty->index, AFI_IP6, type, metric);
+  bgp_redistribute_rmap_set (vty->index, AFI_IP6, type, argv[2]);
+  return bgp_redistribute_set (vty->index, AFI_IP6, type);
+}
+
+DEFUN (no_bgp_redistribute_ipv6,
+       no_bgp_redistribute_ipv6_cmd,
+       "no redistribute (connected|kernel|ospf6|ripng|static)",
+       NO_STR
+       "Redistribute information from another routing protocol\n"
+       "Connected\n"
+       "Kernel routes\n"
+       "Open Shurtest Path First (OSPFv3)\n"
+       "Routing Information Protocol (RIPng)\n"
+       "Static routes\n")
+{
+  int type;
+
+  type = bgp_str2route_type (AFI_IP6, argv[0]);
+  if (! type)
+    {
+      vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  return bgp_redistribute_unset (vty->index, AFI_IP6, type);
+}
+
+DEFUN (no_bgp_redistribute_ipv6_rmap,
+       no_bgp_redistribute_ipv6_rmap_cmd,
+       "no redistribute (connected|kernel|ospf6|ripng|static) route-map WORD",
+       NO_STR
+       "Redistribute information from another routing protocol\n"
+       "Connected\n"
+       "Kernel routes\n"
+       "Open Shurtest Path First (OSPFv3)\n"
+       "Routing Information Protocol (RIPng)\n"
+       "Static routes\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n")
+{
+  int type;
+
+  type = bgp_str2route_type (AFI_IP6, argv[0]);
+  if (! type)
+    {
+      vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  bgp_redistribute_routemap_unset (vty->index, AFI_IP6, type);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_redistribute_ipv6_metric,
+       no_bgp_redistribute_ipv6_metric_cmd,
+       "no redistribute (connected|kernel|ospf6|ripng|static) metric <0-4294967295>",
+       NO_STR
+       "Redistribute information from another routing protocol\n"
+       "Connected\n"
+       "Kernel routes\n"
+       "Open Shurtest Path First (OSPFv3)\n"
+       "Routing Information Protocol (RIPng)\n"
+       "Static routes\n"
+       "Metric for redistributed routes\n"
+       "Default metric\n")
+{
+  int type;
+
+  type = bgp_str2route_type (AFI_IP6, argv[0]);
+  if (! type)
+    {
+      vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  bgp_redistribute_metric_unset (vty->index, AFI_IP6, type);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_bgp_redistribute_ipv6_rmap_metric,
+       no_bgp_redistribute_ipv6_rmap_metric_cmd,
+       "no redistribute (connected|kernel|ospf6|ripng|static) route-map WORD metric <0-4294967295>",
+       NO_STR
+       "Redistribute information from another routing protocol\n"
+       "Connected\n"
+       "Kernel routes\n"
+       "Open Shurtest Path First (OSPFv3)\n"
+       "Routing Information Protocol (RIPng)\n"
+       "Static routes\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n"
+       "Metric for redistributed routes\n"
+       "Default metric\n")
+{
+  int type;
+
+  type = bgp_str2route_type (AFI_IP6, argv[0]);
+  if (! type)
+    {
+      vty_out (vty, "%% Invalid route type%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  bgp_redistribute_metric_unset (vty->index, AFI_IP6, type);
+  bgp_redistribute_routemap_unset (vty->index, AFI_IP6, type);
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_bgp_redistribute_ipv6_rmap_metric,
+       no_bgp_redistribute_ipv6_metric_rmap_cmd,
+       "no redistribute (connected|kernel|ospf6|ripng|static) metric <0-4294967295> route-map WORD",
+       NO_STR
+       "Redistribute information from another routing protocol\n"
+       "Connected\n"
+       "Kernel routes\n"
+       "Open Shurtest Path First (OSPFv3)\n"
+       "Routing Information Protocol (RIPng)\n"
+       "Static routes\n"
+       "Metric for redistributed routes\n"
+       "Default metric\n"
+       "Route map reference\n"
+       "Pointer to route-map entries\n")
+#endif /* HAVE_IPV6 */
+
+int
+bgp_config_write_redistribute (struct vty *vty, struct bgp *bgp, afi_t afi,
+			       safi_t safi, int *write)
+{
+  int i;
+  char *str[] = { "system", "kernel", "connected", "static", "rip",
+		  "ripng", "ospf", "ospf6", "bgp"};
+
+  /* Unicast redistribution only.  */
+  if (safi != SAFI_UNICAST)
+    return 0;
+
+  for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+    {
+      /* Redistribute BGP does not make sense.  */
+      if (bgp->redist[afi][i] && i != ZEBRA_ROUTE_BGP)
+	{
+	  /* Display "address-family" when it is not yet diplayed.  */
+	  bgp_config_write_family_header (vty, afi, safi, write);
+
+	  /* "redistribute" configuration.  */
+	  vty_out (vty, " redistribute %s", str[i]);
+
+	  if (bgp->redist_metric_flag[afi][i])
+	    vty_out (vty, " metric %d", bgp->redist_metric[afi][i]);
+
+	  if (bgp->rmap[afi][i].name)
+	    vty_out (vty, " route-map %s", bgp->rmap[afi][i].name);
+
+	  vty_out (vty, "%s", VTY_NEWLINE);
+	}
+    }
+  return *write;
+}
+
+/* BGP node structure. */
+struct cmd_node bgp_node =
+{
+  BGP_NODE,
+  "%s(config-router)# ",
+  1,
+};
+
+struct cmd_node bgp_ipv4_unicast_node =
+{
+  BGP_IPV4_NODE,
+  "%s(config-router-af)# ",
+  1,
+};
+
+struct cmd_node bgp_ipv4_multicast_node =
+{
+  BGP_IPV4M_NODE,
+  "%s(config-router-af)# ",
+  1,
+};
+
+struct cmd_node bgp_ipv6_unicast_node = 
+{
+  BGP_IPV6_NODE,
+  "%s(config-router-af)# ",
+  1,
+};
+
+struct cmd_node bgp_vpnv4_node =
+{
+  BGP_VPNV4_NODE,
+  "%s(config-router-af)# ",
+  1
+};
+
+void
+bgp_vty_init ()
+{
+  int bgp_config_write (struct vty *);
+  void community_list_vty ();
+
+  /* Install bgp top node. */
+  install_node (&bgp_node, bgp_config_write);
+  install_node (&bgp_ipv4_unicast_node, NULL);
+  install_node (&bgp_ipv4_multicast_node, NULL);
+  install_node (&bgp_ipv6_unicast_node, NULL);
+  install_node (&bgp_vpnv4_node, NULL);
+
+  /* Install default VTY commands to new nodes.  */
+  install_default (BGP_NODE);
+  install_default (BGP_IPV4_NODE);
+  install_default (BGP_IPV4M_NODE);
+  install_default (BGP_IPV6_NODE);
+  install_default (BGP_VPNV4_NODE);
+  
+  /* "bgp multiple-instance" commands. */
+  install_element (CONFIG_NODE, &bgp_multiple_instance_cmd);
+  install_element (CONFIG_NODE, &no_bgp_multiple_instance_cmd);
+
+  /* "bgp config-type" commands. */
+  install_element (CONFIG_NODE, &bgp_config_type_cmd);
+  install_element (CONFIG_NODE, &no_bgp_config_type_cmd);
+
+  /* Dummy commands (Currently not supported) */
+  install_element (BGP_NODE, &no_synchronization_cmd);
+  install_element (BGP_NODE, &no_auto_summary_cmd);
+
+  /* "router bgp" commands. */
+  install_element (CONFIG_NODE, &router_bgp_cmd);
+  install_element (CONFIG_NODE, &router_bgp_view_cmd);
+
+  /* "no router bgp" commands. */
+  install_element (CONFIG_NODE, &no_router_bgp_cmd);
+  install_element (CONFIG_NODE, &no_router_bgp_view_cmd);
+
+  /* "bgp router-id" commands. */
+  install_element (BGP_NODE, &bgp_router_id_cmd);
+  install_element (BGP_NODE, &no_bgp_router_id_cmd);
+  install_element (BGP_NODE, &no_bgp_router_id_val_cmd);
+
+  /* "bgp cluster-id" commands. */
+  install_element (BGP_NODE, &bgp_cluster_id_cmd);
+  install_element (BGP_NODE, &bgp_cluster_id32_cmd);
+  install_element (BGP_NODE, &no_bgp_cluster_id_cmd);
+  install_element (BGP_NODE, &no_bgp_cluster_id_arg_cmd);
+
+  /* "bgp confederation" commands. */
+  install_element (BGP_NODE, &bgp_confederation_identifier_cmd);
+  install_element (BGP_NODE, &no_bgp_confederation_identifier_cmd);
+  install_element (BGP_NODE, &no_bgp_confederation_identifier_arg_cmd);
+
+  /* "bgp confederation peers" commands. */
+  install_element (BGP_NODE, &bgp_confederation_peers_cmd);
+  install_element (BGP_NODE, &no_bgp_confederation_peers_cmd);
+
+  /* "timers bgp" commands. */
+  install_element (BGP_NODE, &bgp_timers_cmd);
+  install_element (BGP_NODE, &no_bgp_timers_cmd);
+  install_element (BGP_NODE, &no_bgp_timers_arg_cmd);
+
+  /* "bgp client-to-client reflection" commands */
+  install_element (BGP_NODE, &no_bgp_client_to_client_reflection_cmd);
+  install_element (BGP_NODE, &bgp_client_to_client_reflection_cmd);
+
+  /* "bgp always-compare-med" commands */
+  install_element (BGP_NODE, &bgp_always_compare_med_cmd);
+  install_element (BGP_NODE, &no_bgp_always_compare_med_cmd);
+  
+  /* "bgp deterministic-med" commands */
+  install_element (BGP_NODE, &bgp_deterministic_med_cmd);
+  install_element (BGP_NODE, &no_bgp_deterministic_med_cmd);
+ 
+  /* "bgp fast-external-failover" commands */
+  install_element (BGP_NODE, &bgp_fast_external_failover_cmd);
+  install_element (BGP_NODE, &no_bgp_fast_external_failover_cmd);
+
+  /* "bgp enforce-first-as" commands */
+  install_element (BGP_NODE, &bgp_enforce_first_as_cmd);
+  install_element (BGP_NODE, &no_bgp_enforce_first_as_cmd);
+
+  /* "bgp bestpath compare-routerid" commands */
+  install_element (BGP_NODE, &bgp_bestpath_compare_router_id_cmd);
+  install_element (BGP_NODE, &no_bgp_bestpath_compare_router_id_cmd);
+
+  /* "bgp bestpath as-path ignore" commands */
+  install_element (BGP_NODE, &bgp_bestpath_aspath_ignore_cmd);
+  install_element (BGP_NODE, &no_bgp_bestpath_aspath_ignore_cmd);
+
+  /* "bgp bestpath med" commands */
+  install_element (BGP_NODE, &bgp_bestpath_med_cmd);
+  install_element (BGP_NODE, &bgp_bestpath_med2_cmd);
+  install_element (BGP_NODE, &bgp_bestpath_med3_cmd);
+  install_element (BGP_NODE, &no_bgp_bestpath_med_cmd);
+  install_element (BGP_NODE, &no_bgp_bestpath_med2_cmd);
+  install_element (BGP_NODE, &no_bgp_bestpath_med3_cmd);
+
+  /* "no bgp default ipv4-unicast" commands. */
+  install_element (BGP_NODE, &no_bgp_default_ipv4_unicast_cmd);
+  install_element (BGP_NODE, &bgp_default_ipv4_unicast_cmd);
+  
+  /* "bgp network import-check" commands. */
+  install_element (BGP_NODE, &bgp_network_import_check_cmd);
+  install_element (BGP_NODE, &no_bgp_network_import_check_cmd);
+
+  /* "bgp default local-preference" commands. */
+  install_element (BGP_NODE, &bgp_default_local_preference_cmd);
+  install_element (BGP_NODE, &no_bgp_default_local_preference_cmd);
+  install_element (BGP_NODE, &no_bgp_default_local_preference_val_cmd);
+
+  /* "neighbor remote-as" commands. */
+  install_element (BGP_NODE, &neighbor_remote_as_cmd);
+  install_element (BGP_NODE, &no_neighbor_cmd);
+  install_element (BGP_NODE, &no_neighbor_remote_as_cmd);
+
+  /* "neighbor peer-group" commands. */
+  install_element (BGP_NODE, &neighbor_peer_group_cmd);
+  install_element (BGP_NODE, &no_neighbor_peer_group_cmd);
+  install_element (BGP_NODE, &no_neighbor_peer_group_remote_as_cmd);
+
+  /* "neighbor local-as" commands. */
+  install_element (BGP_NODE, &neighbor_local_as_cmd);
+  install_element (BGP_NODE, &neighbor_local_as_no_prepend_cmd);
+  install_element (BGP_NODE, &no_neighbor_local_as_cmd);
+  install_element (BGP_NODE, &no_neighbor_local_as_val_cmd);
+  install_element (BGP_NODE, &no_neighbor_local_as_val2_cmd);
+
+  /* "neighbor activate" commands. */
+  install_element (BGP_NODE, &neighbor_activate_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_activate_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_activate_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_activate_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_activate_cmd);
+
+  /* "no neighbor activate" commands. */
+  install_element (BGP_NODE, &no_neighbor_activate_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_activate_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_activate_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_activate_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_activate_cmd);
+
+  /* "neighbor peer-group set" commands. */
+  install_element (BGP_NODE, &neighbor_set_peer_group_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_set_peer_group_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_set_peer_group_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_set_peer_group_cmd);
+
+  /* "no neighbor peer-group unset" commands. */
+  install_element (BGP_NODE, &no_neighbor_set_peer_group_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_set_peer_group_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_set_peer_group_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_set_peer_group_cmd);
+
+  /* "neighbor softreconfiguration inbound" commands.*/
+  install_element (BGP_NODE, &neighbor_soft_reconfiguration_cmd);
+  install_element (BGP_NODE, &no_neighbor_soft_reconfiguration_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_soft_reconfiguration_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_soft_reconfiguration_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_soft_reconfiguration_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_soft_reconfiguration_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_soft_reconfiguration_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_soft_reconfiguration_cmd);
+
+  /* "neighbor attribute-unchanged" commands.  */
+  install_element (BGP_NODE, &neighbor_attr_unchanged_cmd);
+  install_element (BGP_NODE, &neighbor_attr_unchanged1_cmd);
+  install_element (BGP_NODE, &neighbor_attr_unchanged2_cmd);
+  install_element (BGP_NODE, &neighbor_attr_unchanged3_cmd);
+  install_element (BGP_NODE, &neighbor_attr_unchanged4_cmd);
+  install_element (BGP_NODE, &neighbor_attr_unchanged5_cmd);
+  install_element (BGP_NODE, &neighbor_attr_unchanged6_cmd);
+  install_element (BGP_NODE, &neighbor_attr_unchanged7_cmd);
+  install_element (BGP_NODE, &neighbor_attr_unchanged8_cmd);
+  install_element (BGP_NODE, &neighbor_attr_unchanged9_cmd);
+  install_element (BGP_NODE, &neighbor_attr_unchanged10_cmd);
+  install_element (BGP_NODE, &no_neighbor_attr_unchanged_cmd);
+  install_element (BGP_NODE, &no_neighbor_attr_unchanged1_cmd);
+  install_element (BGP_NODE, &no_neighbor_attr_unchanged2_cmd);
+  install_element (BGP_NODE, &no_neighbor_attr_unchanged3_cmd);
+  install_element (BGP_NODE, &no_neighbor_attr_unchanged4_cmd);
+  install_element (BGP_NODE, &no_neighbor_attr_unchanged5_cmd);
+  install_element (BGP_NODE, &no_neighbor_attr_unchanged6_cmd);
+  install_element (BGP_NODE, &no_neighbor_attr_unchanged7_cmd);
+  install_element (BGP_NODE, &no_neighbor_attr_unchanged8_cmd);
+  install_element (BGP_NODE, &no_neighbor_attr_unchanged9_cmd);
+  install_element (BGP_NODE, &no_neighbor_attr_unchanged10_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_attr_unchanged_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_attr_unchanged1_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_attr_unchanged2_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_attr_unchanged3_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_attr_unchanged4_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_attr_unchanged5_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_attr_unchanged6_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_attr_unchanged7_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_attr_unchanged8_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_attr_unchanged9_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_attr_unchanged10_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_attr_unchanged_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_attr_unchanged1_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_attr_unchanged2_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_attr_unchanged3_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_attr_unchanged4_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_attr_unchanged5_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_attr_unchanged6_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_attr_unchanged7_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_attr_unchanged8_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_attr_unchanged9_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_attr_unchanged10_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_attr_unchanged_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_attr_unchanged1_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_attr_unchanged2_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_attr_unchanged3_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_attr_unchanged4_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_attr_unchanged5_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_attr_unchanged6_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_attr_unchanged7_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_attr_unchanged8_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_attr_unchanged9_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_attr_unchanged10_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_attr_unchanged_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_attr_unchanged1_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_attr_unchanged2_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_attr_unchanged3_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_attr_unchanged4_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_attr_unchanged5_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_attr_unchanged6_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_attr_unchanged7_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_attr_unchanged8_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_attr_unchanged9_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_attr_unchanged10_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_attr_unchanged_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_attr_unchanged1_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_attr_unchanged2_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_attr_unchanged3_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_attr_unchanged4_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_attr_unchanged5_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_attr_unchanged6_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_attr_unchanged7_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_attr_unchanged8_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_attr_unchanged9_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_attr_unchanged10_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_attr_unchanged_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_attr_unchanged1_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_attr_unchanged2_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_attr_unchanged3_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_attr_unchanged4_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_attr_unchanged5_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_attr_unchanged6_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_attr_unchanged7_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_attr_unchanged8_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_attr_unchanged9_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_attr_unchanged10_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_attr_unchanged_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_attr_unchanged1_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_attr_unchanged2_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_attr_unchanged3_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_attr_unchanged4_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_attr_unchanged5_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_attr_unchanged6_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_attr_unchanged7_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_attr_unchanged8_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_attr_unchanged9_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_attr_unchanged10_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_attr_unchanged_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_attr_unchanged1_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_attr_unchanged2_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_attr_unchanged3_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_attr_unchanged4_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_attr_unchanged5_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_attr_unchanged6_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_attr_unchanged7_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_attr_unchanged8_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_attr_unchanged9_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_attr_unchanged10_cmd);
+
+  /* "transparent-as" and "transparent-nexthop" for old version
+     compatibility.  */
+  install_element (BGP_NODE, &neighbor_transparent_as_cmd);
+  install_element (BGP_NODE, &neighbor_transparent_nexthop_cmd);
+
+  /* "neighbor next-hop-self" commands. */
+  install_element (BGP_NODE, &neighbor_nexthop_self_cmd);
+  install_element (BGP_NODE, &no_neighbor_nexthop_self_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_nexthop_self_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_nexthop_self_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_nexthop_self_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_nexthop_self_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_nexthop_self_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_nexthop_self_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_nexthop_self_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_nexthop_self_cmd);
+
+  /* "neighbor remove-private-AS" commands. */
+  install_element (BGP_NODE, &neighbor_remove_private_as_cmd);
+  install_element (BGP_NODE, &no_neighbor_remove_private_as_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_remove_private_as_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_remove_private_as_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_remove_private_as_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_remove_private_as_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_remove_private_as_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_remove_private_as_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_remove_private_as_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_remove_private_as_cmd);
+
+  /* "neighbor send-community" commands.*/
+  install_element (BGP_NODE, &neighbor_send_community_cmd);
+  install_element (BGP_NODE, &neighbor_send_community_type_cmd);
+  install_element (BGP_NODE, &no_neighbor_send_community_cmd);
+  install_element (BGP_NODE, &no_neighbor_send_community_type_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_send_community_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_send_community_type_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_send_community_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_send_community_type_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_send_community_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_send_community_type_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_send_community_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_send_community_type_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_send_community_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_send_community_type_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_send_community_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_send_community_type_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_send_community_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_send_community_type_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_send_community_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_send_community_type_cmd);
+
+  /* "neighbor route-reflector" commands.*/
+  install_element (BGP_NODE, &neighbor_route_reflector_client_cmd);
+  install_element (BGP_NODE, &no_neighbor_route_reflector_client_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_route_reflector_client_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_route_reflector_client_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_route_reflector_client_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_route_reflector_client_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_route_reflector_client_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_route_reflector_client_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_route_reflector_client_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_route_reflector_client_cmd);
+
+  /* "neighbor route-server" commands.*/
+  install_element (BGP_NODE, &neighbor_route_server_client_cmd);
+  install_element (BGP_NODE, &no_neighbor_route_server_client_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_route_server_client_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_route_server_client_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_route_server_client_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_route_server_client_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_route_server_client_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_route_server_client_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_route_server_client_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_route_server_client_cmd);
+
+  /* "neighbor passive" commands. */
+  install_element (BGP_NODE, &neighbor_passive_cmd);
+  install_element (BGP_NODE, &no_neighbor_passive_cmd);
+
+  /* "neighbor shutdown" commands. */
+  install_element (BGP_NODE, &neighbor_shutdown_cmd);
+  install_element (BGP_NODE, &no_neighbor_shutdown_cmd);
+
+  /* "neighbor capability route-refresh" commands.*/
+  install_element (BGP_NODE, &neighbor_capability_route_refresh_cmd);
+  install_element (BGP_NODE, &no_neighbor_capability_route_refresh_cmd);
+
+  /* "neighbor capability orf prefix-list" commands.*/
+  install_element (BGP_NODE, &neighbor_capability_orf_prefix_cmd);
+  install_element (BGP_NODE, &no_neighbor_capability_orf_prefix_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_capability_orf_prefix_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_capability_orf_prefix_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_capability_orf_prefix_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_capability_orf_prefix_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_capability_orf_prefix_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_capability_orf_prefix_cmd);
+
+  /* "neighbor capability dynamic" commands.*/
+  install_element (BGP_NODE, &neighbor_capability_dynamic_cmd);
+  install_element (BGP_NODE, &no_neighbor_capability_dynamic_cmd);
+
+  /* "neighbor dont-capability-negotiate" commands. */
+  install_element (BGP_NODE, &neighbor_dont_capability_negotiate_cmd);
+  install_element (BGP_NODE, &no_neighbor_dont_capability_negotiate_cmd);
+
+  /* "neighbor ebgp-multihop" commands. */
+  install_element (BGP_NODE, &neighbor_ebgp_multihop_cmd);
+  install_element (BGP_NODE, &neighbor_ebgp_multihop_ttl_cmd);
+  install_element (BGP_NODE, &no_neighbor_ebgp_multihop_cmd);
+  install_element (BGP_NODE, &no_neighbor_ebgp_multihop_ttl_cmd);
+
+  /* "neighbor enforce-multihop" commands.  */
+  install_element (BGP_NODE, &neighbor_enforce_multihop_cmd);
+  install_element (BGP_NODE, &no_neighbor_enforce_multihop_cmd);
+
+  /* "neighbor description" commands. */
+  install_element (BGP_NODE, &neighbor_description_cmd);
+  install_element (BGP_NODE, &no_neighbor_description_cmd);
+  install_element (BGP_NODE, &no_neighbor_description_val_cmd);
+
+  /* "neighbor update-source" commands. "*/
+  install_element (BGP_NODE, &neighbor_update_source_cmd);
+  install_element (BGP_NODE, &no_neighbor_update_source_cmd);
+
+  /* "neighbor default-originate" commands. */
+  install_element (BGP_NODE, &neighbor_default_originate_cmd);
+  install_element (BGP_NODE, &neighbor_default_originate_rmap_cmd);
+  install_element (BGP_NODE, &no_neighbor_default_originate_cmd);
+  install_element (BGP_NODE, &no_neighbor_default_originate_rmap_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_default_originate_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_default_originate_rmap_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_default_originate_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_default_originate_rmap_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_default_originate_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_default_originate_rmap_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_default_originate_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_default_originate_rmap_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_default_originate_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_default_originate_rmap_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_default_originate_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_default_originate_rmap_cmd);
+
+  /* "neighbor port" commands. */
+  install_element (BGP_NODE, &neighbor_port_cmd);
+  install_element (BGP_NODE, &no_neighbor_port_cmd);
+  install_element (BGP_NODE, &no_neighbor_port_val_cmd);
+
+  /* "neighbor weight" commands. */
+  install_element (BGP_NODE, &neighbor_weight_cmd);
+  install_element (BGP_NODE, &no_neighbor_weight_cmd);
+  install_element (BGP_NODE, &no_neighbor_weight_val_cmd);
+
+  /* "neighbor override-capability" commands. */
+  install_element (BGP_NODE, &neighbor_override_capability_cmd);
+  install_element (BGP_NODE, &no_neighbor_override_capability_cmd);
+
+  /* "neighbor strict-capability-match" commands. */
+  install_element (BGP_NODE, &neighbor_strict_capability_cmd);
+  install_element (BGP_NODE, &no_neighbor_strict_capability_cmd);
+
+  /* "neighbor timers" commands. */
+  install_element (BGP_NODE, &neighbor_timers_cmd);
+  install_element (BGP_NODE, &no_neighbor_timers_cmd);
+
+  /* "neighbor timers connect" commands. */
+  install_element (BGP_NODE, &neighbor_timers_connect_cmd);
+  install_element (BGP_NODE, &no_neighbor_timers_connect_cmd);
+  install_element (BGP_NODE, &no_neighbor_timers_connect_val_cmd);
+
+  /* "neighbor advertisement-interval" commands. */
+  install_element (BGP_NODE, &neighbor_advertise_interval_cmd);
+  install_element (BGP_NODE, &no_neighbor_advertise_interval_cmd);
+  install_element (BGP_NODE, &no_neighbor_advertise_interval_val_cmd);
+
+  /* "neighbor version" commands. */
+  install_element (BGP_NODE, &neighbor_version_cmd);
+  install_element (BGP_NODE, &no_neighbor_version_cmd);
+
+  /* "neighbor interface" commands. */
+  install_element (BGP_NODE, &neighbor_interface_cmd);
+  install_element (BGP_NODE, &no_neighbor_interface_cmd);
+
+  /* "neighbor distribute" commands. */
+  install_element (BGP_NODE, &neighbor_distribute_list_cmd);
+  install_element (BGP_NODE, &no_neighbor_distribute_list_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_distribute_list_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_distribute_list_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_distribute_list_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_distribute_list_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_distribute_list_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_distribute_list_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_distribute_list_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_distribute_list_cmd);
+
+  /* "neighbor prefix-list" commands. */
+  install_element (BGP_NODE, &neighbor_prefix_list_cmd);
+  install_element (BGP_NODE, &no_neighbor_prefix_list_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_prefix_list_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_prefix_list_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_prefix_list_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_prefix_list_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_prefix_list_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_prefix_list_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_prefix_list_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_prefix_list_cmd);
+
+  /* "neighbor filter-list" commands. */
+  install_element (BGP_NODE, &neighbor_filter_list_cmd);
+  install_element (BGP_NODE, &no_neighbor_filter_list_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_filter_list_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_filter_list_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_filter_list_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_filter_list_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_filter_list_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_filter_list_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_filter_list_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_filter_list_cmd);
+
+  /* "neighbor route-map" commands. */
+  install_element (BGP_NODE, &neighbor_route_map_cmd);
+  install_element (BGP_NODE, &no_neighbor_route_map_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_route_map_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_route_map_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_route_map_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_route_map_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_route_map_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_route_map_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_route_map_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_route_map_cmd);
+
+  /* "neighbor unsuppress-map" commands. */
+  install_element (BGP_NODE, &neighbor_unsuppress_map_cmd);
+  install_element (BGP_NODE, &no_neighbor_unsuppress_map_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_unsuppress_map_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_unsuppress_map_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_unsuppress_map_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_unsuppress_map_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_unsuppress_map_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_unsuppress_map_cmd);
+
+  /* "neighbor maximum-prefix" commands. */
+  install_element (BGP_NODE, &neighbor_maximum_prefix_cmd);
+  install_element (BGP_NODE, &neighbor_maximum_prefix_warning_cmd);
+  install_element (BGP_NODE, &no_neighbor_maximum_prefix_cmd);
+  install_element (BGP_NODE, &no_neighbor_maximum_prefix_val_cmd);
+  install_element (BGP_NODE, &no_neighbor_maximum_prefix_val2_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_maximum_prefix_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_maximum_prefix_warning_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_maximum_prefix_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_maximum_prefix_val_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_maximum_prefix_val2_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_maximum_prefix_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_maximum_prefix_warning_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_maximum_prefix_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_maximum_prefix_val_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_maximum_prefix_val2_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_maximum_prefix_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_maximum_prefix_warning_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_maximum_prefix_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_maximum_prefix_val_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_maximum_prefix_val2_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_maximum_prefix_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_maximum_prefix_warning_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_maximum_prefix_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_maximum_prefix_val_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_maximum_prefix_val2_cmd);
+
+  /* "neighbor allowas-in" */
+  install_element (BGP_NODE, &neighbor_allowas_in_cmd);
+  install_element (BGP_NODE, &neighbor_allowas_in_arg_cmd);
+  install_element (BGP_NODE, &no_neighbor_allowas_in_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_allowas_in_cmd);
+  install_element (BGP_IPV4_NODE, &neighbor_allowas_in_arg_cmd);
+  install_element (BGP_IPV4_NODE, &no_neighbor_allowas_in_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_allowas_in_cmd);
+  install_element (BGP_IPV4M_NODE, &neighbor_allowas_in_arg_cmd);
+  install_element (BGP_IPV4M_NODE, &no_neighbor_allowas_in_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_allowas_in_cmd);
+  install_element (BGP_IPV6_NODE, &neighbor_allowas_in_arg_cmd);
+  install_element (BGP_IPV6_NODE, &no_neighbor_allowas_in_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_allowas_in_cmd);
+  install_element (BGP_VPNV4_NODE, &neighbor_allowas_in_arg_cmd);
+  install_element (BGP_VPNV4_NODE, &no_neighbor_allowas_in_cmd);
+
+  /* address-family commands. */
+  install_element (BGP_NODE, &address_family_ipv4_cmd);
+  install_element (BGP_NODE, &address_family_ipv4_safi_cmd);
+#ifdef HAVE_IPV6
+  install_element (BGP_NODE, &address_family_ipv6_cmd);
+  install_element (BGP_NODE, &address_family_ipv6_unicast_cmd);
+#endif /* HAVE_IPV6 */
+  install_element (BGP_NODE, &address_family_vpnv4_cmd);
+  install_element (BGP_NODE, &address_family_vpnv4_unicast_cmd);
+
+  /* "exit-address-family" command. */
+  install_element (BGP_IPV4_NODE, &exit_address_family_cmd);
+  install_element (BGP_IPV4M_NODE, &exit_address_family_cmd);
+  install_element (BGP_IPV6_NODE, &exit_address_family_cmd);
+  install_element (BGP_VPNV4_NODE, &exit_address_family_cmd);
+
+  /* "clear ip bgp commands" */
+  install_element (ENABLE_NODE, &clear_ip_bgp_all_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_instance_all_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_as_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_group_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_external_cmd);
+#ifdef HAVE_IPV6
+  install_element (ENABLE_NODE, &clear_bgp_all_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_instance_all_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_all_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_peer_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_peer_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_peer_group_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_peer_group_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_external_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_external_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_as_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_as_cmd);
+#endif /* HAVE_IPV6 */
+
+  /* "clear ip bgp neighbor soft in" */
+  install_element (ENABLE_NODE, &clear_ip_bgp_all_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_instance_all_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_all_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_all_in_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_instance_all_in_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_in_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_group_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_group_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_group_in_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_external_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_external_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_external_in_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_as_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_as_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_as_in_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_all_ipv4_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_instance_all_ipv4_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_all_ipv4_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_all_ipv4_in_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_instance_all_ipv4_in_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_ipv4_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_ipv4_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_ipv4_in_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_group_ipv4_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_group_ipv4_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_group_ipv4_in_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_external_ipv4_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_external_ipv4_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_external_ipv4_in_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_as_ipv4_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_as_ipv4_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_as_ipv4_in_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_all_vpnv4_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_all_vpnv4_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_vpnv4_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_vpnv4_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_as_vpnv4_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_as_vpnv4_in_cmd);
+#ifdef HAVE_IPV6
+  install_element (ENABLE_NODE, &clear_bgp_all_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_instance_all_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_all_in_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_all_in_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_peer_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_peer_in_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_peer_in_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_peer_group_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_peer_group_in_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_peer_group_in_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_external_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_external_in_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_external_in_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_as_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_as_in_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_as_in_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_all_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_all_in_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_all_in_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_peer_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_peer_in_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_peer_in_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_peer_group_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_peer_group_in_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_peer_group_in_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_external_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_external_in_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_external_in_prefix_filter_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_as_soft_in_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_as_in_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_as_in_prefix_filter_cmd);
+#endif /* HAVE_IPV6 */
+
+  /* "clear ip bgp neighbor soft out" */
+  install_element (ENABLE_NODE, &clear_ip_bgp_all_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_instance_all_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_all_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_group_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_group_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_external_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_external_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_as_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_as_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_all_ipv4_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_instance_all_ipv4_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_all_ipv4_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_ipv4_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_ipv4_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_group_ipv4_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_group_ipv4_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_external_ipv4_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_external_ipv4_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_as_ipv4_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_as_ipv4_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_all_vpnv4_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_all_vpnv4_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_vpnv4_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_vpnv4_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_as_vpnv4_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_as_vpnv4_out_cmd);
+#ifdef HAVE_IPV6
+  install_element (ENABLE_NODE, &clear_bgp_all_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_instance_all_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_all_out_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_peer_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_peer_out_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_peer_group_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_peer_group_out_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_external_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_external_out_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_as_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_as_out_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_all_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_all_out_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_peer_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_peer_out_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_peer_group_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_peer_group_out_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_external_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_external_out_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_as_soft_out_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_as_out_cmd);
+#endif /* HAVE_IPV6 */
+
+  /* "clear ip bgp neighbor soft" */
+  install_element (ENABLE_NODE, &clear_ip_bgp_all_soft_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_instance_all_soft_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_soft_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_group_soft_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_external_soft_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_as_soft_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_all_ipv4_soft_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_instance_all_ipv4_soft_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_ipv4_soft_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_group_ipv4_soft_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_external_ipv4_soft_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_as_ipv4_soft_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_all_vpnv4_soft_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_peer_vpnv4_soft_cmd);
+  install_element (ENABLE_NODE, &clear_ip_bgp_as_vpnv4_soft_cmd);
+#ifdef HAVE_IPV6
+  install_element (ENABLE_NODE, &clear_bgp_all_soft_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_instance_all_soft_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_peer_soft_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_peer_group_soft_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_external_soft_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_as_soft_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_all_soft_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_peer_soft_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_peer_group_soft_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_external_soft_cmd);
+  install_element (ENABLE_NODE, &clear_bgp_ipv6_as_soft_cmd);
+#endif /* HAVE_IPV6 */
+
+  /* "show ip bgp summary" commands. */
+  install_element (VIEW_NODE, &show_ip_bgp_summary_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_instance_summary_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_summary_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_instance_ipv4_summary_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_summary_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_summary_cmd);
+#ifdef HAVE_IPV6
+  install_element (VIEW_NODE, &show_bgp_summary_cmd);
+  install_element (VIEW_NODE, &show_bgp_instance_summary_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_summary_cmd);
+  install_element (VIEW_NODE, &show_bgp_instance_ipv6_summary_cmd);
+#endif /* HAVE_IPV6 */
+  install_element (ENABLE_NODE, &show_ip_bgp_summary_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_instance_summary_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_summary_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_instance_ipv4_summary_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_summary_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_summary_cmd);
+#ifdef HAVE_IPV6
+  install_element (ENABLE_NODE, &show_bgp_summary_cmd);
+  install_element (ENABLE_NODE, &show_bgp_instance_summary_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_summary_cmd);
+  install_element (ENABLE_NODE, &show_bgp_instance_ipv6_summary_cmd);
+#endif /* HAVE_IPV6 */
+
+  /* "show ip bgp neighbors" commands. */
+  install_element (VIEW_NODE, &show_ip_bgp_neighbors_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbors_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_neighbors_peer_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbors_peer_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_neighbors_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_neighbors_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_neighbors_peer_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_neighbors_peer_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_instance_neighbors_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_instance_neighbors_peer_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_neighbors_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbors_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_neighbors_peer_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbors_peer_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_neighbors_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_neighbors_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_neighbors_peer_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_neighbors_peer_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_instance_neighbors_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_instance_neighbors_peer_cmd);
+
+#ifdef HAVE_IPV6
+  install_element (VIEW_NODE, &show_bgp_neighbors_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_neighbors_cmd);
+  install_element (VIEW_NODE, &show_bgp_neighbors_peer_cmd);
+  install_element (VIEW_NODE, &show_bgp_ipv6_neighbors_peer_cmd);
+  install_element (ENABLE_NODE, &show_bgp_neighbors_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_neighbors_cmd);
+  install_element (ENABLE_NODE, &show_bgp_neighbors_peer_cmd);
+  install_element (ENABLE_NODE, &show_bgp_ipv6_neighbors_peer_cmd);
+
+  /* Old commands.  */
+  install_element (VIEW_NODE, &show_ipv6_bgp_summary_cmd);
+  install_element (VIEW_NODE, &show_ipv6_mbgp_summary_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_bgp_summary_cmd);
+  install_element (ENABLE_NODE, &show_ipv6_mbgp_summary_cmd);
+#endif /* HAVE_IPV6 */
+
+  /* "show ip bgp paths" commands. */
+  install_element (VIEW_NODE, &show_ip_bgp_paths_cmd);
+  install_element (VIEW_NODE, &show_ip_bgp_ipv4_paths_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_paths_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_ipv4_paths_cmd);
+
+  /* "show ip bgp community" commands. */
+  install_element (VIEW_NODE, &show_ip_bgp_community_info_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_community_info_cmd);
+
+  /* "show ip bgp attribute-info" commands. */
+  install_element (VIEW_NODE, &show_ip_bgp_attr_info_cmd);
+  install_element (ENABLE_NODE, &show_ip_bgp_attr_info_cmd);
+
+  /* "redistribute" commands.  */
+  install_element (BGP_NODE, &bgp_redistribute_ipv4_cmd);
+  install_element (BGP_NODE, &no_bgp_redistribute_ipv4_cmd);
+  install_element (BGP_NODE, &bgp_redistribute_ipv4_rmap_cmd);
+  install_element (BGP_NODE, &no_bgp_redistribute_ipv4_rmap_cmd);
+  install_element (BGP_NODE, &bgp_redistribute_ipv4_metric_cmd);
+  install_element (BGP_NODE, &no_bgp_redistribute_ipv4_metric_cmd);
+  install_element (BGP_NODE, &bgp_redistribute_ipv4_rmap_metric_cmd);
+  install_element (BGP_NODE, &bgp_redistribute_ipv4_metric_rmap_cmd);
+  install_element (BGP_NODE, &no_bgp_redistribute_ipv4_rmap_metric_cmd);
+  install_element (BGP_NODE, &no_bgp_redistribute_ipv4_metric_rmap_cmd);
+#ifdef HAVE_IPV6
+  install_element (BGP_IPV6_NODE, &bgp_redistribute_ipv6_cmd);
+  install_element (BGP_IPV6_NODE, &no_bgp_redistribute_ipv6_cmd);
+  install_element (BGP_IPV6_NODE, &bgp_redistribute_ipv6_rmap_cmd);
+  install_element (BGP_IPV6_NODE, &no_bgp_redistribute_ipv6_rmap_cmd);
+  install_element (BGP_IPV6_NODE, &bgp_redistribute_ipv6_metric_cmd);
+  install_element (BGP_IPV6_NODE, &no_bgp_redistribute_ipv6_metric_cmd);
+  install_element (BGP_IPV6_NODE, &bgp_redistribute_ipv6_rmap_metric_cmd);
+  install_element (BGP_IPV6_NODE, &bgp_redistribute_ipv6_metric_rmap_cmd);
+  install_element (BGP_IPV6_NODE, &no_bgp_redistribute_ipv6_rmap_metric_cmd);
+  install_element (BGP_IPV6_NODE, &no_bgp_redistribute_ipv6_metric_rmap_cmd);
+#endif /* HAVE_IPV6 */
+
+  /* Community-list. */
+  community_list_vty ();
+}
+
+#include "memory.h"
+#include "bgp_regex.h"
+#include "bgp_clist.h"
+#include "bgp_ecommunity.h"
+
+/* VTY functions.  */
+
+/* Direction value to string conversion.  */
+char *
+community_direct_str (int direct)
+{
+  switch (direct)
+    {
+    case COMMUNITY_DENY:
+      return "deny";
+      break;
+    case COMMUNITY_PERMIT:
+      return "permit";
+      break;
+    default:
+      return "unknown";
+      break;
+    }
+}
+
+/* Display error string.  */
+void
+community_list_perror (struct vty *vty, int ret)
+{
+  switch (ret)
+    {
+    case COMMUNITY_LIST_ERR_CANT_FIND_LIST:
+      vty_out (vty, "%% Can't find communit-list%s", VTY_NEWLINE);
+      break;
+    case COMMUNITY_LIST_ERR_MALFORMED_VAL:
+      vty_out (vty, "%% Malformed community-list value%s", VTY_NEWLINE);
+      break;
+    case COMMUNITY_LIST_ERR_STANDARD_CONFLICT:
+      vty_out (vty, "%% Community name conflict, previously defined as standard community%s", VTY_NEWLINE);
+      break;
+    case COMMUNITY_LIST_ERR_EXPANDED_CONFLICT:
+      vty_out (vty, "%% Community name conflict, previously defined as expanded community%s", VTY_NEWLINE);
+      break;
+    }
+}
+
+/* VTY interface for community_set() function.  */
+int
+community_list_set_vty (struct vty *vty, int argc, char **argv, int style,
+			int reject_all_digit_name)
+{
+  int ret;
+  int direct;
+  char *str;
+
+  /* Check the list type. */
+  if (strncmp (argv[1], "p", 1) == 0)
+    direct = COMMUNITY_PERMIT;
+  else if (strncmp (argv[1], "d", 1) == 0)
+    direct = COMMUNITY_DENY;
+  else
+    {
+      vty_out (vty, "%% Matching condition must be permit or deny%s",
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* All digit name check.  */
+  if (reject_all_digit_name && all_digit (argv[0]))
+    {
+      vty_out (vty, "%% Community name cannot have all digits%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Concat community string argument.  */
+  if (argc > 1)
+    str = argv_concat (argv, argc, 2);
+  else
+    str = NULL;
+
+  /* When community_list_set() return nevetive value, it means
+     malformed community string.  */
+  ret = community_list_set (bgp_clist, argv[0], str, direct, style);
+
+  /* Free temporary community list string allocated by
+     argv_concat().  */
+  if (str)
+    XFREE (MTYPE_TMP, str);
+
+  if (ret < 0)
+    {
+      /* Display error string.  */
+      community_list_perror (vty, ret);
+      return CMD_WARNING;
+    }
+
+  return CMD_SUCCESS;
+}
+
+/* Community-list delete with name.  */
+int
+community_list_unset_all_vty (struct vty *vty, char *name)
+{
+  int ret;
+
+  ret = community_list_unset (bgp_clist, name, NULL, 0, COMMUNITY_LIST_AUTO);
+
+  if (ret < 0)
+    {
+      community_list_perror (vty, ret);
+      return CMD_WARNING;
+    }
+  return CMD_SUCCESS;
+}
+
+/* Communiyt-list entry delete.  */
+int
+community_list_unset_vty (struct vty *vty, int argc, char **argv, int style)
+{
+  int ret;
+  int direct;
+  char *str;
+
+  /* Check the list direct. */
+  if (strncmp (argv[1], "p", 1) == 0)
+    direct = COMMUNITY_PERMIT;
+  else if (strncmp (argv[1], "d", 1) == 0)
+    direct = COMMUNITY_DENY;
+  else
+    {
+      vty_out (vty, "%% Matching condition must be permit or deny%s",
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Concat community string argument.  */
+  str = argv_concat (argv, argc, 2);
+
+  /* Unset community list.  */
+  ret = community_list_unset (bgp_clist, argv[0], str, direct, style);
+
+  /* Free temporary community list string allocated by
+     argv_concat().  */
+  XFREE (MTYPE_TMP, str);
+
+  if (ret < 0)
+    {
+      community_list_perror (vty, ret);
+      return CMD_WARNING;
+    }
+
+  return CMD_SUCCESS;
+}
+
+/* "community-list" keyword help string.  */
+#define COMMUNITY_LIST_STR "Add a community list entry\n"
+#define COMMUNITY_VAL_STR  "Community number in aa:nn format or internet|local-AS|no-advertise|no-export\n"
+
+DEFUN (ip_community_list,
+       ip_community_list_cmd,
+       "ip community-list WORD (deny|permit) .AA:NN",
+       IP_STR
+       COMMUNITY_LIST_STR
+       "Community list name\n"
+       "Specify community to reject\n"
+       "Specify community to accept\n"
+       COMMUNITY_VAL_STR)
+{
+  return community_list_set_vty (vty, argc, argv, COMMUNITY_LIST_AUTO, 1);
+}
+
+DEFUN (ip_community_list_standard,
+       ip_community_list_standard_cmd,
+       "ip community-list <1-99> (deny|permit) .AA:NN",
+       IP_STR
+       COMMUNITY_LIST_STR
+       "Community list number (standard)\n"
+       "Specify community to reject\n"
+       "Specify community to accept\n"
+       COMMUNITY_VAL_STR)
+{
+  return community_list_set_vty (vty, argc, argv, COMMUNITY_LIST_STANDARD, 0);
+}
+
+ALIAS (ip_community_list_standard,
+       ip_community_list_standard2_cmd,
+       "ip community-list <1-99> (deny|permit)",
+       IP_STR
+       COMMUNITY_LIST_STR
+       "Community list number (standard)\n"
+       "Specify community to reject\n"
+       "Specify community to accept\n")
+
+DEFUN (ip_community_list_expanded,
+       ip_community_list_expanded_cmd,
+       "ip community-list <100-199> (deny|permit) .LINE",
+       IP_STR
+       COMMUNITY_LIST_STR
+       "Community list number (expanded)\n"
+       "Specify community to reject\n"
+       "Specify community to accept\n"
+       "An ordered list as a regular-expression\n")
+{
+  return community_list_set_vty (vty, argc, argv, COMMUNITY_LIST_EXPANDED, 0);
+}
+
+DEFUN (ip_community_list_name_standard,
+       ip_community_list_name_standard_cmd,
+       "ip community-list standard WORD (deny|permit) .AA:NN",
+       IP_STR
+       COMMUNITY_LIST_STR
+       "Add a standard community-list entry\n"
+       "Community list name\n"
+       "Specify community to reject\n"
+       "Specify community to accept\n"
+       COMMUNITY_VAL_STR)
+{
+  return community_list_set_vty (vty, argc, argv, COMMUNITY_LIST_STANDARD, 1);
+}
+
+ALIAS (ip_community_list_name_standard,
+       ip_community_list_name_standard2_cmd,
+       "ip community-list standard WORD (deny|permit)",
+       IP_STR
+       COMMUNITY_LIST_STR
+       "Add a standard community-list entry\n"
+       "Community list name\n"
+       "Specify community to reject\n"
+       "Specify community to accept\n")
+
+DEFUN (ip_community_list_name_expanded,
+       ip_community_list_name_expanded_cmd,
+       "ip community-list expanded WORD (deny|permit) .LINE",
+       IP_STR
+       COMMUNITY_LIST_STR
+       "Add an expanded community-list entry\n"
+       "Community list name\n"
+       "Specify community to reject\n"
+       "Specify community to accept\n"
+       "An ordered list as a regular-expression\n")
+{
+  return community_list_set_vty (vty, argc, argv, COMMUNITY_LIST_EXPANDED, 1);
+}
+
+DEFUN (no_ip_community_list_all,
+       no_ip_community_list_all_cmd,
+       "no ip community-list (WORD|<1-99>|<100-199>)",
+       NO_STR
+       IP_STR
+       COMMUNITY_LIST_STR
+       "Community list name\n"
+       "Community list number (standard)\n"
+       "Community list number (expanded)\n")
+{
+  return community_list_unset_all_vty (vty, argv[0]);
+}
+
+DEFUN (no_ip_community_list_name_all,
+       no_ip_community_list_name_all_cmd,
+       "no ip community-list (standard|expanded) WORD",
+       NO_STR
+       IP_STR
+       COMMUNITY_LIST_STR
+       "Add a standard community-list entry\n"
+       "Add an expanded community-list entry\n"
+       "Community list name\n")
+{
+  return community_list_unset_all_vty (vty, argv[1]);
+}
+
+DEFUN (no_ip_community_list,
+       no_ip_community_list_cmd,
+       "no ip community-list WORD (deny|permit) .AA:NN",
+       NO_STR
+       IP_STR
+       COMMUNITY_LIST_STR
+       "Community list name\n"
+       "Specify community to reject\n"
+       "Specify community to accept\n"
+       COMMUNITY_VAL_STR)
+{
+  return community_list_unset_vty (vty, argc, argv, COMMUNITY_LIST_AUTO);
+}
+
+DEFUN (no_ip_community_list_standard,
+       no_ip_community_list_standard_cmd,
+       "no ip community-list <1-99> (deny|permit) .AA:NN",
+       NO_STR
+       IP_STR
+       COMMUNITY_LIST_STR
+       "Community list number (standard)\n"
+       "Specify community to reject\n"
+       "Specify community to accept\n"
+       COMMUNITY_VAL_STR)
+{
+  return community_list_unset_vty (vty, argc, argv, COMMUNITY_LIST_STANDARD);
+}
+
+DEFUN (no_ip_community_list_expanded,
+       no_ip_community_list_expanded_cmd,
+       "no ip community-list <100-199> (deny|permit) .LINE",
+       NO_STR
+       IP_STR
+       COMMUNITY_LIST_STR
+       "Community list number (expanded)\n"
+       "Specify community to reject\n"
+       "Specify community to accept\n"
+       "An ordered list as a regular-expression\n")
+{
+  return community_list_unset_vty (vty, argc, argv, COMMUNITY_LIST_EXPANDED);
+}
+
+DEFUN (no_ip_community_list_name_standard,
+       no_ip_community_list_name_standard_cmd,
+       "no ip community-list standard WORD (deny|permit) .AA:NN",
+       NO_STR
+       IP_STR
+       COMMUNITY_LIST_STR
+       "Specify a standard community-list\n"
+       "Community list name\n"
+       "Specify community to reject\n"
+       "Specify community to accept\n"
+       COMMUNITY_VAL_STR)
+{
+  return community_list_unset_vty (vty, argc, argv, COMMUNITY_LIST_STANDARD);
+}
+
+DEFUN (no_ip_community_list_name_expanded,
+       no_ip_community_list_name_expanded_cmd,
+       "no ip community-list expanded WORD (deny|permit) .LINE",
+       NO_STR
+       IP_STR
+       COMMUNITY_LIST_STR
+       "Specify an expanded community-list\n"
+       "Community list name\n"
+       "Specify community to reject\n"
+       "Specify community to accept\n"
+       "An ordered list as a regular-expression\n")
+{
+  return community_list_unset_vty (vty, argc, argv, COMMUNITY_LIST_EXPANDED);
+}
+
+void
+community_list_show (struct vty *vty, struct community_list *list)
+{
+  struct community_entry *entry;
+
+  for (entry = list->head; entry; entry = entry->next)
+    {
+      if (entry == list->head)
+	{
+	  if (all_digit (list->name))
+	    vty_out (vty, "Community %s list %s%s",
+		     entry->style == COMMUNITY_LIST_STANDARD ?
+		     "standard" : "(expanded) access",
+		     list->name, VTY_NEWLINE);
+	  else
+	    vty_out (vty, "Named Community %s list %s%s",
+		     entry->style == COMMUNITY_LIST_STANDARD ?
+		     "standard" : "expanded",
+		     list->name, VTY_NEWLINE);
+	}
+      if (entry->any)
+	vty_out (vty, "    %s%s",
+		 community_direct_str (entry->direct), VTY_NEWLINE);
+      else
+	vty_out (vty, "    %s %s%s",
+		 community_direct_str (entry->direct),
+		 entry->style == COMMUNITY_LIST_STANDARD
+		 ? community_str (entry->u.com) : entry->config,
+		 VTY_NEWLINE);
+    }
+}
+
+DEFUN (show_ip_community_list,
+       show_ip_community_list_cmd,
+       "show ip community-list",
+       SHOW_STR
+       IP_STR
+       "List community-list\n")
+{
+  struct community_list *list;
+  struct community_list_master *cm;
+
+  cm = community_list_master_lookup (bgp_clist, COMMUNITY_LIST_AUTO);
+  if (! cm)
+    return CMD_SUCCESS;
+
+  for (list = cm->num.head; list; list = list->next)
+    community_list_show (vty, list);
+
+  for (list = cm->str.head; list; list = list->next)
+    community_list_show (vty, list);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_community_list_arg,
+       show_ip_community_list_arg_cmd,
+       "show ip community-list (<1-199>|WORD)",
+       SHOW_STR
+       IP_STR
+       "List community-list\n"
+       "Community-list number\n"
+       "Community-list name\n")
+{
+  struct community_list *list;
+
+  list = community_list_lookup (bgp_clist, argv[0], COMMUNITY_LIST_AUTO);
+  if (! list)
+    {
+      vty_out (vty, "%% Can't find communit-list%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  community_list_show (vty, list);
+
+  return CMD_SUCCESS;
+}
+
+int
+extcommunity_list_set_vty (struct vty *vty, int argc, char **argv, int style,
+			   int reject_all_digit_name)
+{
+  int ret;
+  int direct;
+  char *str;
+
+  /* Check the list type. */
+  if (strncmp (argv[1], "p", 1) == 0)
+    direct = COMMUNITY_PERMIT;
+  else if (strncmp (argv[1], "d", 1) == 0)
+    direct = COMMUNITY_DENY;
+  else
+    {
+      vty_out (vty, "%% Matching condition must be permit or deny%s",
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* All digit name check.  */
+  if (reject_all_digit_name && all_digit (argv[0]))
+    {
+      vty_out (vty, "%% Community name cannot have all digits%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Concat community string argument.  */
+  if (argc > 1)
+    str = argv_concat (argv, argc, 2);
+  else
+    str = NULL;
+
+  ret = extcommunity_list_set (bgp_clist, argv[0], str, direct, style);
+
+  /* Free temporary community list string allocated by
+     argv_concat().  */
+  if (str)
+    XFREE (MTYPE_TMP, str);
+
+  if (ret < 0)
+    {
+      community_list_perror (vty, ret);
+      return CMD_WARNING;
+    }
+  return CMD_SUCCESS;
+}
+
+int
+extcommunity_list_unset_all_vty (struct vty *vty, char *name)
+{
+  int ret;
+
+  ret = extcommunity_list_unset (bgp_clist, name, NULL, 0, EXTCOMMUNITY_LIST_AUTO);
+
+  if (ret < 0)
+    {
+      community_list_perror (vty, ret);
+      return CMD_WARNING;
+    }
+  return CMD_SUCCESS;
+}
+
+int
+extcommunity_list_unset_vty (struct vty *vty, int argc, char **argv, int style)
+{
+  int ret;
+  int direct;
+  char *str;
+
+  /* Check the list direct. */
+  if (strncmp (argv[1], "p", 1) == 0)
+    direct = COMMUNITY_PERMIT;
+  else if (strncmp (argv[1], "d", 1) == 0)
+    direct = COMMUNITY_DENY;
+  else
+    {
+      vty_out (vty, "%% Matching condition must be permit or deny%s",
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  /* Concat community string argument.  */
+  str = argv_concat (argv, argc, 2);
+
+  /* Unset community list.  */
+  ret = extcommunity_list_unset (bgp_clist, argv[0], str, direct, style);
+
+  /* Free temporary community list string allocated by
+     argv_concat().  */
+  XFREE (MTYPE_TMP, str);
+
+  if (ret < 0)
+    {
+      community_list_perror (vty, ret);
+      return CMD_WARNING;
+    }
+
+  return CMD_SUCCESS;
+}
+
+/* "extcommunity-list" keyword help string.  */
+#define EXTCOMMUNITY_LIST_STR "Add a extended community list entry\n"
+#define EXTCOMMUNITY_VAL_STR  "Extended community attribute in 'rt aa:nn_or_IPaddr:nn' OR 'soo aa:nn_or_IPaddr:nn' format\n"
+
+DEFUN (ip_extcommunity_list_standard,
+       ip_extcommunity_list_standard_cmd,
+       "ip extcommunity-list <1-99> (deny|permit) .AA:NN",
+       IP_STR
+       EXTCOMMUNITY_LIST_STR
+       "Extended Community list number (standard)\n"
+       "Specify community to reject\n"
+       "Specify community to accept\n"
+       EXTCOMMUNITY_VAL_STR)
+{
+  return extcommunity_list_set_vty (vty, argc, argv, EXTCOMMUNITY_LIST_STANDARD, 0);
+}
+
+ALIAS (ip_extcommunity_list_standard,
+       ip_extcommunity_list_standard2_cmd,
+       "ip extcommunity-list <1-99> (deny|permit)",
+       IP_STR
+       EXTCOMMUNITY_LIST_STR
+       "Extended Community list number (standard)\n"
+       "Specify community to reject\n"
+       "Specify community to accept\n")
+
+DEFUN (ip_extcommunity_list_expanded,
+       ip_extcommunity_list_expanded_cmd,
+       "ip extcommunity-list <100-199> (deny|permit) .LINE",
+       IP_STR
+       EXTCOMMUNITY_LIST_STR
+       "Extended Community list number (expanded)\n"
+       "Specify community to reject\n"
+       "Specify community to accept\n"
+       "An ordered list as a regular-expression\n")
+{
+  return extcommunity_list_set_vty (vty, argc, argv, EXTCOMMUNITY_LIST_EXPANDED, 0);
+}
+
+DEFUN (ip_extcommunity_list_name_standard,
+       ip_extcommunity_list_name_standard_cmd,
+       "ip extcommunity-list standard WORD (deny|permit) .AA:NN",
+       IP_STR
+       EXTCOMMUNITY_LIST_STR
+       "Specify standard extcommunity-list\n"
+       "Extended Community list name\n"
+       "Specify community to reject\n"
+       "Specify community to accept\n"
+       EXTCOMMUNITY_VAL_STR)
+{
+  return extcommunity_list_set_vty (vty, argc, argv, EXTCOMMUNITY_LIST_STANDARD, 1);
+}
+
+ALIAS (ip_extcommunity_list_name_standard,
+       ip_extcommunity_list_name_standard2_cmd,
+       "ip extcommunity-list standard WORD (deny|permit)",
+       IP_STR
+       EXTCOMMUNITY_LIST_STR
+       "Specify standard extcommunity-list\n"
+       "Extended Community list name\n"
+       "Specify community to reject\n"
+       "Specify community to accept\n")
+
+DEFUN (ip_extcommunity_list_name_expanded,
+       ip_extcommunity_list_name_expanded_cmd,
+       "ip extcommunity-list expanded WORD (deny|permit) .LINE",
+       IP_STR
+       EXTCOMMUNITY_LIST_STR
+       "Specify expanded extcommunity-list\n"
+       "Extended Community list name\n"
+       "Specify community to reject\n"
+       "Specify community to accept\n"
+       "An ordered list as a regular-expression\n")
+{
+  return extcommunity_list_set_vty (vty, argc, argv, EXTCOMMUNITY_LIST_EXPANDED, 1);
+}
+
+DEFUN (no_ip_extcommunity_list_all,
+       no_ip_extcommunity_list_all_cmd,
+       "no ip extcommunity-list (<1-99>|<100-199>)",
+       NO_STR
+       IP_STR
+       EXTCOMMUNITY_LIST_STR
+       "Extended Community list number (standard)\n"
+       "Extended Community list number (expanded)\n")
+{
+  return extcommunity_list_unset_all_vty (vty, argv[0]);
+}
+
+DEFUN (no_ip_extcommunity_list_name_all,
+       no_ip_extcommunity_list_name_all_cmd,
+       "no ip extcommunity-list (standard|expanded) WORD",
+       NO_STR
+       IP_STR
+       EXTCOMMUNITY_LIST_STR
+       "Specify standard extcommunity-list\n"
+       "Specify expanded extcommunity-list\n"
+       "Extended Community list name\n")
+{
+  return extcommunity_list_unset_all_vty (vty, argv[1]);
+}
+
+DEFUN (no_ip_extcommunity_list_standard,
+       no_ip_extcommunity_list_standard_cmd,
+       "no ip extcommunity-list <1-99> (deny|permit) .AA:NN",
+       NO_STR
+       IP_STR
+       EXTCOMMUNITY_LIST_STR
+       "Extended Community list number (standard)\n"
+       "Specify community to reject\n"
+       "Specify community to accept\n"
+       EXTCOMMUNITY_VAL_STR)
+{
+  return extcommunity_list_unset_vty (vty, argc, argv, EXTCOMMUNITY_LIST_STANDARD);
+}
+
+DEFUN (no_ip_extcommunity_list_expanded,
+       no_ip_extcommunity_list_expanded_cmd,
+       "no ip extcommunity-list <100-199> (deny|permit) .LINE",
+       NO_STR
+       IP_STR
+       EXTCOMMUNITY_LIST_STR
+       "Extended Community list number (expanded)\n"
+       "Specify community to reject\n"
+       "Specify community to accept\n"
+       "An ordered list as a regular-expression\n")
+{
+  return extcommunity_list_unset_vty (vty, argc, argv, EXTCOMMUNITY_LIST_EXPANDED);
+}
+
+DEFUN (no_ip_extcommunity_list_name_standard,
+       no_ip_extcommunity_list_name_standard_cmd,
+       "no ip extcommunity-list standard WORD (deny|permit) .AA:NN",
+       NO_STR
+       IP_STR
+       EXTCOMMUNITY_LIST_STR
+       "Specify standard extcommunity-list\n"
+       "Extended Community list name\n"
+       "Specify community to reject\n"
+       "Specify community to accept\n"
+       EXTCOMMUNITY_VAL_STR)
+{
+  return extcommunity_list_unset_vty (vty, argc, argv, EXTCOMMUNITY_LIST_STANDARD);
+}
+
+DEFUN (no_ip_extcommunity_list_name_expanded,
+       no_ip_extcommunity_list_name_expanded_cmd,
+       "no ip extcommunity-list expanded WORD (deny|permit) .LINE",
+       NO_STR
+       IP_STR
+       EXTCOMMUNITY_LIST_STR
+       "Specify expanded extcommunity-list\n"
+       "Community list name\n"
+       "Specify community to reject\n"
+       "Specify community to accept\n"
+       "An ordered list as a regular-expression\n")
+{
+  return extcommunity_list_unset_vty (vty, argc, argv, EXTCOMMUNITY_LIST_EXPANDED);
+}
+
+void
+extcommunity_list_show (struct vty *vty, struct community_list *list)
+{
+  struct community_entry *entry;
+
+  for (entry = list->head; entry; entry = entry->next)
+    {
+      if (entry == list->head)
+	{
+	  if (all_digit (list->name))
+	    vty_out (vty, "Extended community %s list %s%s",
+		     entry->style == EXTCOMMUNITY_LIST_STANDARD ?
+		     "standard" : "(expanded) access",
+		     list->name, VTY_NEWLINE);
+	  else
+	    vty_out (vty, "Named extended community %s list %s%s",
+		     entry->style == EXTCOMMUNITY_LIST_STANDARD ?
+		     "standard" : "expanded",
+		     list->name, VTY_NEWLINE);
+	}
+      if (entry->any)
+	vty_out (vty, "    %s%s",
+		 community_direct_str (entry->direct), VTY_NEWLINE);
+      else
+	vty_out (vty, "    %s %s%s",
+		 community_direct_str (entry->direct),
+		 entry->style == EXTCOMMUNITY_LIST_STANDARD ?
+		 entry->u.ecom->str : entry->config,
+		 VTY_NEWLINE);
+    }
+}
+
+DEFUN (show_ip_extcommunity_list,
+       show_ip_extcommunity_list_cmd,
+       "show ip extcommunity-list",
+       SHOW_STR
+       IP_STR
+       "List extended-community list\n")
+{
+  struct community_list *list;
+  struct community_list_master *cm;
+
+  cm = community_list_master_lookup (bgp_clist, EXTCOMMUNITY_LIST_AUTO);
+  if (! cm)
+    return CMD_SUCCESS;
+
+  for (list = cm->num.head; list; list = list->next)
+    extcommunity_list_show (vty, list);
+
+  for (list = cm->str.head; list; list = list->next)
+    extcommunity_list_show (vty, list);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (show_ip_extcommunity_list_arg,
+       show_ip_extcommunity_list_arg_cmd,
+       "show ip extcommunity-list (<1-199>|WORD)",
+       SHOW_STR
+       IP_STR
+       "List extended-community list\n"
+       "Extcommunity-list number\n"
+       "Extcommunity-list name\n")
+{
+  struct community_list *list;
+
+  list = community_list_lookup (bgp_clist, argv[0], EXTCOMMUNITY_LIST_AUTO);
+  if (! list)
+    {
+      vty_out (vty, "%% Can't find extcommunit-list%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  extcommunity_list_show (vty, list);
+
+  return CMD_SUCCESS;
+}
+
+/* Return configuration string of community-list entry.  */
+static char *
+community_list_config_str (struct community_entry *entry)
+{
+  char *str;
+
+  if (entry->any)
+    str = "";
+  else
+    {
+      if (entry->style == COMMUNITY_LIST_STANDARD)
+	str = community_str (entry->u.com);
+      else
+	str = entry->config;
+    }
+  return str;
+}
+
+/* Display community-list and extcommunity-list configuration.  */
+int
+community_list_config_write (struct vty *vty)
+{
+  struct community_list *list;
+  struct community_entry *entry;
+  struct community_list_master *cm;
+  int write = 0;
+
+  /* Community-list.  */
+  cm = community_list_master_lookup (bgp_clist, COMMUNITY_LIST_AUTO);
+
+  for (list = cm->num.head; list; list = list->next)
+    for (entry = list->head; entry; entry = entry->next)
+      {
+	if (atol (list->name) < 200)
+	  vty_out (vty, "ip community-list %s %s %s%s",
+		   list->name, community_direct_str (entry->direct),
+		   community_list_config_str (entry),
+		   VTY_NEWLINE);
+	else
+	  vty_out (vty, "ip community-list %s %s %s %s%s",
+		   entry->style == COMMUNITY_LIST_STANDARD
+		   ? "standard" : "expanded",
+		   list->name, community_direct_str (entry->direct),
+		   community_list_config_str (entry),
+		   VTY_NEWLINE);
+	write++;
+      }
+  for (list = cm->str.head; list; list = list->next)
+    for (entry = list->head; entry; entry = entry->next)
+      {
+	vty_out (vty, "ip community-list %s %s %s %s%s",
+		 entry->style == COMMUNITY_LIST_STANDARD
+		 ? "standard" : "expanded",
+		 list->name, community_direct_str (entry->direct),
+		 community_list_config_str (entry),
+		 VTY_NEWLINE);
+	write++;
+      }
+
+  /* Extcommunity-list.  */
+  cm = community_list_master_lookup (bgp_clist, EXTCOMMUNITY_LIST_AUTO);
+
+  for (list = cm->num.head; list; list = list->next)
+    for (entry = list->head; entry; entry = entry->next)
+      {
+	if (atol (list->name) < 200)
+	  vty_out (vty, "ip extcommunity-list %s %s %s%s",
+		   list->name, community_direct_str (entry->direct),
+		   community_list_config_str (entry), VTY_NEWLINE);
+	else
+	  vty_out (vty, "ip extcommunity-list %s %s %s %s%s",
+		   entry->style == EXTCOMMUNITY_LIST_STANDARD
+		   ? "standard" : "expanded",
+		   list->name, community_direct_str (entry->direct),
+		   community_list_config_str (entry), VTY_NEWLINE);
+	write++;
+      }
+  for (list = cm->str.head; list; list = list->next)
+    for (entry = list->head; entry; entry = entry->next)
+      {
+	vty_out (vty, "ip extcommunity-list %s %s %s %s%s",
+		 entry->style == EXTCOMMUNITY_LIST_STANDARD
+		 ? "standard" : "expanded",
+		 list->name, community_direct_str (entry->direct),
+		 community_list_config_str (entry), VTY_NEWLINE);
+	write++;
+      }
+  return write;
+}
+
+struct cmd_node community_list_node =
+{
+  COMMUNITY_LIST_NODE,
+  "",
+  1				/* Export to vtysh.  */
+};
+
+void
+community_list_vty ()
+{
+  install_node (&community_list_node, community_list_config_write);
+
+  /* Community-list.  */
+  install_element (CONFIG_NODE, &ip_community_list_cmd);
+  install_element (CONFIG_NODE, &ip_community_list_standard_cmd);
+  install_element (CONFIG_NODE, &ip_community_list_standard2_cmd);
+  install_element (CONFIG_NODE, &ip_community_list_expanded_cmd);
+  install_element (CONFIG_NODE, &ip_community_list_name_standard_cmd);
+  install_element (CONFIG_NODE, &ip_community_list_name_standard2_cmd);
+  install_element (CONFIG_NODE, &ip_community_list_name_expanded_cmd);
+  install_element (CONFIG_NODE, &no_ip_community_list_all_cmd);
+  install_element (CONFIG_NODE, &no_ip_community_list_name_all_cmd);
+  install_element (CONFIG_NODE, &no_ip_community_list_cmd);
+  install_element (CONFIG_NODE, &no_ip_community_list_standard_cmd);
+  install_element (CONFIG_NODE, &no_ip_community_list_expanded_cmd);
+  install_element (CONFIG_NODE, &no_ip_community_list_name_standard_cmd);
+  install_element (CONFIG_NODE, &no_ip_community_list_name_expanded_cmd);
+  install_element (VIEW_NODE, &show_ip_community_list_cmd);
+  install_element (VIEW_NODE, &show_ip_community_list_arg_cmd);
+  install_element (ENABLE_NODE, &show_ip_community_list_cmd);
+  install_element (ENABLE_NODE, &show_ip_community_list_arg_cmd);
+
+  /* Extcommunity-list.  */
+  install_element (CONFIG_NODE, &ip_extcommunity_list_standard_cmd);
+  install_element (CONFIG_NODE, &ip_extcommunity_list_standard2_cmd);
+  install_element (CONFIG_NODE, &ip_extcommunity_list_expanded_cmd);
+  install_element (CONFIG_NODE, &ip_extcommunity_list_name_standard_cmd);
+  install_element (CONFIG_NODE, &ip_extcommunity_list_name_standard2_cmd);
+  install_element (CONFIG_NODE, &ip_extcommunity_list_name_expanded_cmd);
+  install_element (CONFIG_NODE, &no_ip_extcommunity_list_all_cmd);
+  install_element (CONFIG_NODE, &no_ip_extcommunity_list_name_all_cmd);
+  install_element (CONFIG_NODE, &no_ip_extcommunity_list_standard_cmd);
+  install_element (CONFIG_NODE, &no_ip_extcommunity_list_expanded_cmd);
+  install_element (CONFIG_NODE, &no_ip_extcommunity_list_name_standard_cmd);
+  install_element (CONFIG_NODE, &no_ip_extcommunity_list_name_expanded_cmd);
+  install_element (VIEW_NODE, &show_ip_extcommunity_list_cmd);
+  install_element (VIEW_NODE, &show_ip_extcommunity_list_arg_cmd);
+  install_element (ENABLE_NODE, &show_ip_extcommunity_list_cmd);
+  install_element (ENABLE_NODE, &show_ip_extcommunity_list_arg_cmd);
+}
diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h
new file mode 100644
index 0000000..15ad581
--- /dev/null
+++ b/bgpd/bgp_vty.h
@@ -0,0 +1,21 @@
+/* BGP VTY interface.
+   Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+void bgp_vty_init ();
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
new file mode 100644
index 0000000..3e5cdd2
--- /dev/null
+++ b/bgpd/bgp_zebra.c
@@ -0,0 +1,1001 @@
+/* zebra client
+   Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "command.h"
+#include "stream.h"
+#include "network.h"
+#include "prefix.h"
+#include "log.h"
+#include "sockunion.h"
+#include "zclient.h"
+#include "routemap.h"
+#include "thread.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_nexthop.h"
+#include "bgpd/bgp_zebra.h"
+#include "bgpd/bgp_fsm.h"
+
+/* All information about zebra. */
+static struct zclient *zclient = NULL;
+
+/* Update default router id. */
+int
+bgp_if_update (struct interface *ifp)
+{
+  struct bgp *bgp;
+  listnode cn;
+  struct listnode *nn;
+  struct listnode *nm;
+  struct peer *peer;
+
+  for (cn = listhead (ifp->connected); cn; nextnode (cn))
+    {
+      struct connected *co;
+      struct in_addr addr;
+
+      co = getdata (cn);
+
+      if (co->address->family == AF_INET)
+	{
+	  addr = co->address->u.prefix4;
+
+	  /* Ignore NET127. */
+	  if (IPV4_NET127 (ntohl (addr.s_addr)))
+	    continue;
+
+	  LIST_LOOP (bm->bgp, bgp, nn)
+	    {
+	      /* Respect configured router id */
+	      if (! (bgp->config & BGP_CONFIG_ROUTER_ID))
+		if (ntohl (bgp->router_id.s_addr) < ntohl (addr.s_addr))
+		  {
+		    bgp->router_id = addr;
+		    LIST_LOOP (bgp->peer, peer, nm)
+		      {
+			peer->local_id = addr;
+		      }
+		  }
+	    }
+	}
+    }
+  return 0;
+}
+
+int
+bgp_if_update_all ()
+{
+  listnode node;
+  struct interface *ifp;
+
+  for (node = listhead (iflist); node; node = nextnode (node))
+    {
+      ifp = getdata (node);
+      bgp_if_update (ifp);
+    }
+  return 0;
+}
+
+/* Inteface addition message from zebra. */
+int
+bgp_interface_add (int command, struct zclient *zclient, zebra_size_t length)
+{
+  struct interface *ifp;
+
+  ifp = zebra_interface_add_read (zclient->ibuf);
+  bgp_if_update (ifp);
+
+  return 0;
+}
+
+int
+bgp_interface_delete (int command, struct zclient *zclient,
+		      zebra_size_t length)
+{
+  struct stream *s;
+  struct interface *ifp;
+
+  s = zclient->ibuf;
+  ifp = zebra_interface_state_read (s);
+
+  return 0;
+}
+
+int
+bgp_interface_up (int command, struct zclient *zclient, zebra_size_t length)
+{
+  struct stream *s;
+  struct interface *ifp;
+  struct connected *c;
+  listnode node;
+
+  s = zclient->ibuf;
+  ifp = zebra_interface_state_read (s);
+
+  if (! ifp)
+    return 0;
+
+  for (node = listhead (ifp->connected); node; nextnode (node))
+    {
+      c = getdata (node);
+      bgp_connected_add (c);
+    }
+
+  return 0;
+}
+
+int
+bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length)
+{
+  struct stream *s;
+  struct interface *ifp;
+  struct connected *c;
+  listnode node;
+
+  s = zclient->ibuf;
+  ifp = zebra_interface_state_read (s);
+  if (! ifp)
+    return 0;
+
+  for (node = listhead (ifp->connected); node; nextnode (node))
+    {
+      c = getdata (node);
+      bgp_connected_delete (c);
+    }
+
+  /* Fast external-failover (Currently IPv4 only) */
+  {
+    struct listnode *nn, *nm;
+    struct bgp *bgp;
+    struct peer *peer;
+    struct interface *peer_if;
+
+    LIST_LOOP (bm->bgp, bgp, nn)
+      {
+	if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
+	  continue;
+
+	LIST_LOOP (bgp->peer, peer, nm)
+	  {
+	    if (peer->ttl != 1)
+	      continue;
+
+	    if (peer->su.sa.sa_family == AF_INET)
+	      peer_if = if_lookup_by_ipv4 (&peer->su.sin.sin_addr);
+	    else
+	      continue;
+
+	    if (ifp == peer_if)
+	      BGP_EVENT_ADD (peer, BGP_Stop);
+	  }
+      }
+  }
+
+  return 0;
+}
+
+int
+bgp_interface_address_add (int command, struct zclient *zclient,
+			   zebra_size_t length)
+{
+  struct connected *ifc;
+
+  ifc = zebra_interface_address_add_read (zclient->ibuf);
+
+  if (ifc == NULL)
+    return 0;
+
+  bgp_if_update (ifc->ifp);
+
+  if (if_is_up (ifc->ifp))
+    bgp_connected_add (ifc);
+
+  return 0;
+}
+
+int
+bgp_interface_address_delete (int command, struct zclient *zclient,
+			      zebra_size_t length)
+{
+  struct connected *ifc;
+
+  ifc = zebra_interface_address_delete_read (zclient->ibuf);
+
+  if (ifc == NULL)
+    return 0;
+
+  bgp_if_update (ifc->ifp);
+
+  if (if_is_up (ifc->ifp))
+    bgp_connected_delete (ifc);
+
+  connected_free (ifc);
+
+  return 0;
+}
+
+/* Zebra route add and delete treatment. */
+int
+zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length)
+{
+  struct stream *s;
+  struct zapi_ipv4 api;
+  unsigned long ifindex;
+  struct in_addr nexthop;
+  struct prefix_ipv4 p;
+
+  s = zclient->ibuf;
+  ifindex = 0;
+  nexthop.s_addr = 0;
+
+  /* Type, flags, message. */
+  api.type = stream_getc (s);
+  api.flags = stream_getc (s);
+  api.message = stream_getc (s);
+
+  /* IPv4 prefix. */
+  memset (&p, 0, sizeof (struct prefix_ipv4));
+  p.family = AF_INET;
+  p.prefixlen = stream_getc (s);
+  stream_get (&p.prefix, s, PSIZE (p.prefixlen));
+
+  /* Nexthop, ifindex, distance, metric. */
+  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
+    {
+      api.nexthop_num = stream_getc (s);
+      nexthop.s_addr = stream_get_ipv4 (s);
+    }
+  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
+    {
+      api.ifindex_num = stream_getc (s);
+      ifindex = stream_getl (s);
+    }
+  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
+    api.distance = stream_getc (s);
+  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
+    api.metric = stream_getl (s);
+  else
+    api.metric = 0;
+
+  if (command == ZEBRA_IPV4_ROUTE_ADD)
+    bgp_redistribute_add ((struct prefix *)&p, &nexthop, api.metric, api.type);
+  else
+    bgp_redistribute_delete ((struct prefix *)&p, api.type);
+
+  return 0;
+}
+
+#ifdef HAVE_IPV6
+/* Zebra route add and delete treatment. */
+int
+zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length)
+{
+  struct stream *s;
+  struct zapi_ipv6 api;
+  unsigned long ifindex;
+  struct in6_addr nexthop;
+  struct prefix_ipv6 p;
+
+  s = zclient->ibuf;
+  ifindex = 0;
+  memset (&nexthop, 0, sizeof (struct in6_addr));
+
+  /* Type, flags, message. */
+  api.type = stream_getc (s);
+  api.flags = stream_getc (s);
+  api.message = stream_getc (s);
+
+  /* IPv6 prefix. */
+  memset (&p, 0, sizeof (struct prefix_ipv6));
+  p.family = AF_INET6;
+  p.prefixlen = stream_getc (s);
+  stream_get (&p.prefix, s, PSIZE (p.prefixlen));
+
+  /* Nexthop, ifindex, distance, metric. */
+  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
+    {
+      api.nexthop_num = stream_getc (s);
+      stream_get (&nexthop, s, 16);
+    }
+  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
+    {
+      api.ifindex_num = stream_getc (s);
+      ifindex = stream_getl (s);
+    }
+  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
+    api.distance = stream_getc (s);
+  else
+    api.distance = 0;
+  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
+    api.metric = stream_getl (s);
+  else
+    api.metric = 0;
+
+  /* Simply ignore link-local address. */
+  if (IN6_IS_ADDR_LINKLOCAL (&p.prefix))
+    return 0;
+
+  if (command == ZEBRA_IPV6_ROUTE_ADD)
+    bgp_redistribute_add ((struct prefix *)&p, NULL, api.metric, api.type);
+  else
+    bgp_redistribute_delete ((struct prefix *) &p, api.type);
+  
+  return 0;
+}
+#endif /* HAVE_IPV6 */
+
+struct interface *
+if_lookup_by_ipv4 (struct in_addr *addr)
+{
+  listnode ifnode;
+  listnode cnode;
+  struct interface *ifp;
+  struct connected *connected;
+  struct prefix_ipv4 p;
+  struct prefix *cp; 
+  
+  p.family = AF_INET;
+  p.prefix = *addr;
+  p.prefixlen = IPV4_MAX_BITLEN;
+
+  for (ifnode = listhead (iflist); ifnode; nextnode (ifnode))
+    {
+      ifp = getdata (ifnode);
+
+      for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
+	{
+	  connected = getdata (cnode);
+	  cp = connected->address;
+	    
+	  if (cp->family == AF_INET)
+	    if (prefix_match (cp, (struct prefix *)&p))
+	      return ifp;
+	}
+    }
+  return NULL;
+}
+
+struct interface *
+if_lookup_by_ipv4_exact (struct in_addr *addr)
+{
+  listnode ifnode;
+  listnode cnode;
+  struct interface *ifp;
+  struct connected *connected;
+  struct prefix *cp; 
+  
+  for (ifnode = listhead (iflist); ifnode; nextnode (ifnode))
+    {
+      ifp = getdata (ifnode);
+
+      for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
+	{
+	  connected = getdata (cnode);
+	  cp = connected->address;
+	    
+	  if (cp->family == AF_INET)
+	    if (IPV4_ADDR_SAME (&cp->u.prefix4, addr))
+	      return ifp;
+	}
+    }
+  return NULL;
+}
+
+#ifdef HAVE_IPV6
+struct interface *
+if_lookup_by_ipv6 (struct in6_addr *addr)
+{
+  listnode ifnode;
+  listnode cnode;
+  struct interface *ifp;
+  struct connected *connected;
+  struct prefix_ipv6 p;
+  struct prefix *cp; 
+  
+  p.family = AF_INET6;
+  p.prefix = *addr;
+  p.prefixlen = IPV6_MAX_BITLEN;
+
+  for (ifnode = listhead (iflist); ifnode; nextnode (ifnode))
+    {
+      ifp = getdata (ifnode);
+
+      for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
+	{
+	  connected = getdata (cnode);
+	  cp = connected->address;
+	    
+	  if (cp->family == AF_INET6)
+	    if (prefix_match (cp, (struct prefix *)&p))
+	      return ifp;
+	}
+    }
+  return NULL;
+}
+
+struct interface *
+if_lookup_by_ipv6_exact (struct in6_addr *addr)
+{
+  listnode ifnode;
+  listnode cnode;
+  struct interface *ifp;
+  struct connected *connected;
+  struct prefix *cp; 
+
+  for (ifnode = listhead (iflist); ifnode; nextnode (ifnode))
+    {
+      ifp = getdata (ifnode);
+
+      for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
+	{
+	  connected = getdata (cnode);
+	  cp = connected->address;
+	    
+	  if (cp->family == AF_INET6)
+	    if (IPV6_ADDR_SAME (&cp->u.prefix6, addr))
+	      return ifp;
+	}
+    }
+  return NULL;
+}
+
+int
+if_get_ipv6_global (struct interface *ifp, struct in6_addr *addr)
+{
+  listnode cnode;
+  struct connected *connected;
+  struct prefix *cp; 
+  
+  for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
+    {
+      connected = getdata (cnode);
+      cp = connected->address;
+	    
+      if (cp->family == AF_INET6)
+	if (! IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6))
+	  {
+	    memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN);
+	    return 1;
+	  }
+    }
+  return 0;
+}
+
+int
+if_get_ipv6_local (struct interface *ifp, struct in6_addr *addr)
+{
+  listnode cnode;
+  struct connected *connected;
+  struct prefix *cp; 
+  
+  for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
+    {
+      connected = getdata (cnode);
+      cp = connected->address;
+	    
+      if (cp->family == AF_INET6)
+	if (IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6))
+	  {
+	    memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN);
+	    return 1;
+	  }
+    }
+  return 0;
+}
+#endif /* HAVE_IPV6 */
+
+int
+bgp_nexthop_set (union sockunion *local, union sockunion *remote, 
+		 struct bgp_nexthop *nexthop, struct peer *peer)
+{
+  int ret = 0;
+  struct interface *ifp = NULL;
+
+  memset (nexthop, 0, sizeof (struct bgp_nexthop));
+
+  if (!local)
+    return -1;
+  if (!remote)
+    return -1;
+
+  if (local->sa.sa_family == AF_INET)
+    {
+      nexthop->v4 = local->sin.sin_addr;
+      ifp = if_lookup_by_ipv4 (&local->sin.sin_addr);
+    }
+#ifdef HAVE_IPV6
+  if (local->sa.sa_family == AF_INET6)
+    {
+      if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr))
+	{
+	  if (peer->ifname)
+	    ifp = if_lookup_by_index (if_nametoindex (peer->ifname));
+	}
+      else
+	ifp = if_lookup_by_ipv6 (&local->sin6.sin6_addr);
+    }
+#endif /* HAVE_IPV6 */
+
+  if (!ifp)
+    return -1;
+
+  nexthop->ifp = ifp;
+
+  /* IPv4 connection. */
+  if (local->sa.sa_family == AF_INET)
+    {
+#ifdef HAVE_IPV6
+      /* IPv6 nexthop*/
+      ret = if_get_ipv6_global (ifp, &nexthop->v6_global);
+
+      /* There is no global nexthop. */
+      if (!ret)
+	if_get_ipv6_local (ifp, &nexthop->v6_global);
+      else
+	if_get_ipv6_local (ifp, &nexthop->v6_local);
+#endif /* HAVE_IPV6 */
+    }
+
+#ifdef HAVE_IPV6
+  /* IPv6 connection. */
+  if (local->sa.sa_family == AF_INET6)
+    {
+      struct interface *direct = NULL;
+
+      /* IPv4 nexthop.  I don't care about it. */
+      if (peer->local_id.s_addr)
+	nexthop->v4 = peer->local_id;
+
+      /* Global address*/
+      if (! IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr))
+	{
+	  memcpy (&nexthop->v6_global, &local->sin6.sin6_addr, 
+		  IPV6_MAX_BYTELEN);
+
+	  /* If directory connected set link-local address. */
+	  direct = if_lookup_by_ipv6 (&remote->sin6.sin6_addr);
+	  if (direct)
+	    if_get_ipv6_local (ifp, &nexthop->v6_local);
+	}
+      else
+	/* Link-local address. */
+	{
+	  ret = if_get_ipv6_global (ifp, &nexthop->v6_global);
+
+	  /* If there is no global address.  Set link-local address as
+             global.  I know this break RFC specification... */
+	  if (!ret)
+	    memcpy (&nexthop->v6_global, &local->sin6.sin6_addr, 
+		    IPV6_MAX_BYTELEN);
+	  else
+	    memcpy (&nexthop->v6_local, &local->sin6.sin6_addr, 
+		    IPV6_MAX_BYTELEN);
+	}
+    }
+
+  if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr) ||
+      if_lookup_by_ipv6 (&remote->sin6.sin6_addr))
+    peer->shared_network = 1;
+  else
+    peer->shared_network = 0;
+
+  /* KAME stack specific treatment.  */
+#ifdef KAME
+  if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_global)
+      && IN6_LINKLOCAL_IFINDEX (nexthop->v6_global))
+    {
+      SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_global, 0);
+    }
+  if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_local)
+      && IN6_LINKLOCAL_IFINDEX (nexthop->v6_local))
+    {
+      SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_local, 0);
+    }
+#endif /* KAME */
+#endif /* HAVE_IPV6 */
+  return ret;
+}
+
+#ifdef HAVE_IPV6
+unsigned int
+bgp_ifindex_by_nexthop (struct in6_addr *addr)
+{
+  listnode ifnode;
+  listnode cnode;
+  struct interface *ifp;
+  struct connected *connected;
+  struct prefix_ipv6 p;
+  
+  p.family = AF_INET6;
+  p.prefix = *addr;
+  p.prefixlen = IPV6_MAX_BITLEN;
+
+  for (ifnode = listhead (iflist); ifnode; nextnode (ifnode))
+    {
+      ifp = getdata (ifnode);
+
+      for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
+	{
+	  struct prefix *cp; 
+
+	  connected = getdata (cnode);
+	  cp = connected->address;
+	    
+	  if (cp->family == AF_INET6)
+	    {
+	      if (prefix_match (cp, (struct prefix *)&p))
+		return ifp->ifindex;
+	    }
+	}
+    }
+  return 0;
+}
+#endif /* HAVE_IPV6 */
+
+void
+bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp)
+{
+  int flags;
+  u_char distance;
+  struct peer *peer;
+
+  if (zclient->sock < 0)
+    return;
+
+  if (! zclient->redist[ZEBRA_ROUTE_BGP])
+    return;
+
+  flags = 0;
+  peer = info->peer;
+
+  if (peer_sort (peer) == BGP_PEER_IBGP || peer_sort (peer) == BGP_PEER_CONFED)
+    {
+      SET_FLAG (flags, ZEBRA_FLAG_IBGP);
+      SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
+    }
+
+  if ((peer_sort (peer) == BGP_PEER_EBGP && peer->ttl != 1)
+      || CHECK_FLAG (peer->flags, PEER_FLAG_ENFORCE_MULTIHOP))
+    SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
+
+  if (p->family == AF_INET)
+    {
+      struct zapi_ipv4 api;
+      struct in_addr *nexthop;
+
+      api.flags = flags;
+      nexthop = &info->attr->nexthop;
+
+      api.type = ZEBRA_ROUTE_BGP;
+      api.message = 0;
+      SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
+      api.nexthop_num = 1;
+      api.nexthop = &nexthop;
+      api.ifindex_num = 0;
+      SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
+      api.metric = info->attr->med;
+
+      distance = bgp_distance_apply (p, info, bgp);
+
+      if (distance)
+	{
+	  SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
+	  api.distance = distance;
+	}
+      zapi_ipv4_add (zclient, (struct prefix_ipv4 *) p, &api);
+    }
+#ifdef HAVE_IPV6
+  /* We have to think about a IPv6 link-local address curse. */
+  if (p->family == AF_INET6)
+    {
+      unsigned int ifindex;
+      struct in6_addr *nexthop;
+      struct zapi_ipv6 api;
+
+      ifindex = 0;
+      nexthop = NULL;
+
+      /* Only global address nexthop exists. */
+      if (info->attr->mp_nexthop_len == 16)
+	nexthop = &info->attr->mp_nexthop_global;
+      
+      /* If both global and link-local address present. */
+      if (info->attr->mp_nexthop_len == 32)
+	{
+	  /* Workaround for Cisco's nexthop bug.  */
+	  if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->mp_nexthop_global)
+	      && peer->su_remote->sa.sa_family == AF_INET6)
+	    nexthop = &peer->su_remote->sin6.sin6_addr;
+	  else
+	    nexthop = &info->attr->mp_nexthop_local;
+
+	  if (info->peer->nexthop.ifp)
+	    ifindex = info->peer->nexthop.ifp->ifindex;
+	}
+
+      if (nexthop == NULL)
+	return;
+
+      if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex)
+	{
+	  if (info->peer->ifname)
+	    ifindex = if_nametoindex (info->peer->ifname);
+	  else if (info->peer->nexthop.ifp)
+	    ifindex = info->peer->nexthop.ifp->ifindex;
+	}
+
+      /* Make Zebra API structure. */
+      api.flags = flags;
+      api.type = ZEBRA_ROUTE_BGP;
+      api.message = 0;
+      SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
+      api.nexthop_num = 1;
+      api.nexthop = &nexthop;
+      SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
+      api.ifindex_num = 1;
+      api.ifindex = &ifindex;
+      SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
+      api.metric = info->attr->med;
+
+      zapi_ipv6_add (zclient, (struct prefix_ipv6 *) p, &api);
+    }
+#endif /* HAVE_IPV6 */
+}
+
+void
+bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info)
+{
+  int flags;
+  struct peer *peer;
+
+  if (zclient->sock < 0)
+    return;
+
+  if (! zclient->redist[ZEBRA_ROUTE_BGP])
+    return;
+
+  peer = info->peer;
+  flags = 0;
+
+  if (peer_sort (peer) == BGP_PEER_IBGP)
+    {
+      SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
+      SET_FLAG (flags, ZEBRA_FLAG_IBGP);
+    }
+
+  if ((peer_sort (peer) == BGP_PEER_EBGP && peer->ttl != 1)
+      || CHECK_FLAG (peer->flags, PEER_FLAG_ENFORCE_MULTIHOP))
+    SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
+
+  if (p->family == AF_INET)
+    {
+      struct zapi_ipv4 api;
+      struct in_addr *nexthop;
+
+      api.flags = flags;
+      nexthop = &info->attr->nexthop;
+
+      api.type = ZEBRA_ROUTE_BGP;
+      api.message = 0;
+      SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
+      api.nexthop_num = 1;
+      api.nexthop = &nexthop;
+      api.ifindex_num = 0;
+      SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
+      api.metric = info->attr->med;
+
+      zapi_ipv4_delete (zclient, (struct prefix_ipv4 *) p, &api);
+    }
+#ifdef HAVE_IPV6
+  /* We have to think about a IPv6 link-local address curse. */
+  if (p->family == AF_INET6)
+    {
+      struct zapi_ipv6 api;
+      unsigned int ifindex;
+      struct in6_addr *nexthop;
+
+      ifindex = 0;
+      nexthop = NULL;
+
+      /* Only global address nexthop exists. */
+      if (info->attr->mp_nexthop_len == 16)
+	nexthop = &info->attr->mp_nexthop_global;
+
+      /* If both global and link-local address present. */
+      if (info->attr->mp_nexthop_len == 32)
+	{
+	  nexthop = &info->attr->mp_nexthop_local;
+	  if (info->peer->nexthop.ifp)
+	    ifindex = info->peer->nexthop.ifp->ifindex;
+	}
+
+      if (nexthop == NULL)
+	return;
+
+      if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex)
+	if (info->peer->ifname)
+	  ifindex = if_nametoindex (info->peer->ifname);
+
+      api.flags = flags;
+      api.type = ZEBRA_ROUTE_BGP;
+      api.message = 0;
+      SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
+      api.nexthop_num = 1;
+      api.nexthop = &nexthop;
+      SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
+      api.ifindex_num = 1;
+      api.ifindex = &ifindex;
+      SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
+      api.metric = info->attr->med;
+
+      zapi_ipv6_delete (zclient, (struct prefix_ipv6 *) p, &api);
+    }
+#endif /* HAVE_IPV6 */
+}
+
+/* Other routes redistribution into BGP. */
+int
+bgp_redistribute_set (struct bgp *bgp, afi_t afi, int type)
+{
+  /* Set flag to BGP instance. */
+  bgp->redist[afi][type] = 1;
+
+  /* Return if already redistribute flag is set. */
+  if (zclient->redist[type])
+    return CMD_WARNING;
+
+  zclient->redist[type] = 1;
+
+  /* Return if zebra connection is not established. */
+  if (zclient->sock < 0)
+    return CMD_WARNING;
+    
+  /* Send distribute add message to zebra. */
+  zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient->sock, type);
+
+  return CMD_SUCCESS;
+}
+
+/* Redistribute with route-map specification.  */
+int
+bgp_redistribute_rmap_set (struct bgp *bgp, afi_t afi, int type, char *name)
+{
+  if (bgp->rmap[afi][type].name
+      && (strcmp (bgp->rmap[afi][type].name, name) == 0))
+    return 0;
+
+  if (bgp->rmap[afi][type].name)
+    free (bgp->rmap[afi][type].name);
+  bgp->rmap[afi][type].name = strdup (name);
+  bgp->rmap[afi][type].map = route_map_lookup_by_name (name);
+
+  return 1;
+}
+
+/* Redistribute with metric specification.  */
+int
+bgp_redistribute_metric_set (struct bgp *bgp, afi_t afi, int type,
+			     u_int32_t metric)
+{
+  if (bgp->redist_metric_flag[afi][type]
+      && bgp->redist_metric[afi][type] == metric)
+    return 0;
+
+  bgp->redist_metric_flag[afi][type] = 1;
+  bgp->redist_metric[afi][type] = metric;
+
+  return 1;
+}
+
+/* Unset redistribution.  */
+int
+bgp_redistribute_unset (struct bgp *bgp, afi_t afi, int type)
+{
+  /* Unset flag from BGP instance. */
+  bgp->redist[afi][type] = 0;
+
+  /* Unset route-map. */
+  if (bgp->rmap[afi][type].name)
+    free (bgp->rmap[afi][type].name);
+  bgp->rmap[afi][type].name = NULL;
+  bgp->rmap[afi][type].map = NULL;
+
+  /* Unset metric. */
+  bgp->redist_metric_flag[afi][type] = 0;
+  bgp->redist_metric[afi][type] = 0;
+
+  /* Return if zebra connection is disabled. */
+  if (! zclient->redist[type])
+    return CMD_WARNING;
+  zclient->redist[type] = 0;
+
+  if (bgp->redist[AFI_IP][type] == 0 
+      && bgp->redist[AFI_IP6][type] == 0 
+      && zclient->sock >= 0)
+    /* Send distribute delete message to zebra. */
+    zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient->sock, type);
+  
+  /* Withdraw redistributed routes from current BGP's routing table. */
+  bgp_redistribute_withdraw (bgp, afi, type);
+
+  return CMD_SUCCESS;
+}
+
+/* Unset redistribution route-map configuration.  */
+int
+bgp_redistribute_routemap_unset (struct bgp *bgp, afi_t afi, int type)
+{
+  if (! bgp->rmap[afi][type].name)
+    return 0;
+
+  /* Unset route-map. */
+  free (bgp->rmap[afi][type].name);
+  bgp->rmap[afi][type].name = NULL;
+  bgp->rmap[afi][type].map = NULL;
+
+  return 1;
+}
+
+/* Unset redistribution metric configuration.  */
+int
+bgp_redistribute_metric_unset (struct bgp *bgp, afi_t afi, int type)
+{
+  if (! bgp->redist_metric_flag[afi][type])
+    return 0;
+
+  /* Unset metric. */
+  bgp->redist_metric_flag[afi][type] = 0;
+  bgp->redist_metric[afi][type] = 0;
+
+  return 1;
+}
+
+void
+bgp_zclient_reset ()
+{
+  zclient_reset (zclient);
+}
+
+void
+bgp_zebra_init (int enable)
+{
+  /* Set default values. */
+  zclient = zclient_new ();
+  zclient_init (zclient, ZEBRA_ROUTE_BGP);
+  zclient->interface_add = bgp_interface_add;
+  zclient->interface_delete = bgp_interface_delete;
+  zclient->interface_address_add = bgp_interface_address_add;
+  zclient->interface_address_delete = bgp_interface_address_delete;
+  zclient->ipv4_route_add = zebra_read_ipv4;
+  zclient->ipv4_route_delete = zebra_read_ipv4;
+  zclient->interface_up = bgp_interface_up;
+  zclient->interface_down = bgp_interface_down;
+#ifdef HAVE_IPV6
+  zclient->ipv6_route_add = zebra_read_ipv6;
+  zclient->ipv6_route_delete = zebra_read_ipv6;
+#endif /* HAVE_IPV6 */
+
+  /* Interface related init. */
+  if_init ();
+}
diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h
new file mode 100644
index 0000000..1620c84
--- /dev/null
+++ b/bgpd/bgp_zebra.h
@@ -0,0 +1,39 @@
+/* zebra connection and redistribute fucntions.
+   Copyright (C) 1999 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+int bgp_if_update_all ();
+int bgp_config_write_redistribute (struct vty *, struct bgp *, afi_t, safi_t,
+				   int *);
+void bgp_zebra_announce (struct prefix *, struct bgp_info *, struct bgp *);
+void bgp_zebra_withdraw (struct prefix *, struct bgp_info *);
+
+int bgp_redistribute_set (struct bgp *, afi_t, int);
+int bgp_redistribute_rmap_set (struct bgp *, afi_t, int, char *);
+int bgp_redistribute_metric_set (struct bgp *, afi_t, int, u_int32_t);
+int bgp_redistribute_unset (struct bgp *, afi_t, int);
+int bgp_redistribute_routemap_unset (struct bgp *, afi_t, int);
+int bgp_redistribute_metric_unset (struct bgp *, afi_t, int);
+
+struct interface *if_lookup_by_ipv4 (struct in_addr *);
+struct interface *if_lookup_by_ipv4_exact (struct in_addr *);
+#ifdef HAVE_IPV6
+struct interface *if_lookup_by_ipv6 (struct in6_addr *);
+struct interface *if_lookup_by_ipv6_exact (struct in6_addr *);
+#endif /* HAVE_IPV6 */
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
new file mode 100644
index 0000000..f116a0c
--- /dev/null
+++ b/bgpd/bgpd.c
@@ -0,0 +1,4601 @@
+/* BGP-4, BGP-4+ daemon program
+   Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "prefix.h"
+#include "thread.h"
+#include "buffer.h"
+#include "stream.h"
+#include "command.h"
+#include "sockunion.h"
+#include "network.h"
+#include "memory.h"
+#include "filter.h"
+#include "routemap.h"
+#include "str.h"
+#include "log.h"
+#include "plist.h"
+#include "linklist.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_table.h"
+#include "bgpd/bgp_aspath.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_dump.h"
+#include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_community.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_regex.h"
+#include "bgpd/bgp_clist.h"
+#include "bgpd/bgp_fsm.h"
+#include "bgpd/bgp_packet.h"
+#include "bgpd/bgp_zebra.h"
+#include "bgpd/bgp_open.h"
+#include "bgpd/bgp_filter.h"
+#include "bgpd/bgp_nexthop.h"
+#include "bgpd/bgp_damp.h"
+#include "bgpd/bgp_mplsvpn.h"
+#include "bgpd/bgp_advertise.h"
+#include "bgpd/bgp_network.h"
+#include "bgpd/bgp_vty.h"
+#ifdef HAVE_SNMP
+#include "bgpd/bgp_snmp.h"
+#endif /* HAVE_SNMP */
+
+/* BGP process wide configuration.  */
+static struct bgp_master bgp_master;
+
+/* BGP process wide configuration pointer to export.  */
+struct bgp_master *bm;
+
+/* BGP community-list.  */
+struct community_list_handler *bgp_clist;
+
+/* BGP global flag manipulation.  */
+int
+bgp_option_set (int flag)
+{
+  switch (flag)
+    {
+    case BGP_OPT_NO_FIB:
+    case BGP_OPT_MULTIPLE_INSTANCE:
+    case BGP_OPT_CONFIG_CISCO:
+      SET_FLAG (bm->options, flag);
+      break;
+    default:
+      return BGP_ERR_INVALID_FLAG;
+      break;
+    }
+  return 0;
+}
+
+int
+bgp_option_unset (int flag)
+{
+  switch (flag)
+    {
+    case BGP_OPT_MULTIPLE_INSTANCE:
+      if (listcount (bm->bgp) > 1)
+	return BGP_ERR_MULTIPLE_INSTANCE_USED;
+      /* Fall through.  */
+    case BGP_OPT_NO_FIB:
+    case BGP_OPT_CONFIG_CISCO:
+      UNSET_FLAG (bm->options, flag);
+      break;
+    default:
+      return BGP_ERR_INVALID_FLAG;
+      break;
+    }
+  return 0;
+}
+
+int
+bgp_option_check (int flag)
+{
+  return CHECK_FLAG (bm->options, flag);
+}
+
+/* BGP flag manipulation.  */
+int
+bgp_flag_set (struct bgp *bgp, int flag)
+{
+  SET_FLAG (bgp->flags, flag);
+  return 0;
+}
+
+int
+bgp_flag_unset (struct bgp *bgp, int flag)
+{
+  UNSET_FLAG (bgp->flags, flag);
+  return 0;
+}
+
+int
+bgp_flag_check (struct bgp *bgp, int flag)
+{
+  return CHECK_FLAG (bgp->flags, flag);
+}
+
+/* Internal function to set BGP structure configureation flag.  */
+static void
+bgp_config_set (struct bgp *bgp, int config)
+{
+  SET_FLAG (bgp->config, config);
+}
+
+static void
+bgp_config_unset (struct bgp *bgp, int config)
+{
+  UNSET_FLAG (bgp->config, config);
+}
+
+static int
+bgp_config_check (struct bgp *bgp, int config)
+{
+  return CHECK_FLAG (bgp->config, config);
+}
+
+/* Set BGP router identifier. */
+int
+bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
+{
+  struct peer *peer;
+  struct listnode *nn;
+
+  if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
+      && IPV4_ADDR_SAME (&bgp->router_id, id))
+    return 0;
+
+  IPV4_ADDR_COPY (&bgp->router_id, id);
+  bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
+
+  /* Set all peer's local identifier with this value. */
+  LIST_LOOP (bgp->peer, peer, nn)
+    {
+      IPV4_ADDR_COPY (&peer->local_id, id);
+
+      if (peer->status == Established)
+	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+    }
+  return 0;
+}
+
+/* Unset BGP router identifier. */
+int
+bgp_router_id_unset (struct bgp *bgp)
+{
+  struct peer *peer;
+  struct listnode *nn;
+
+  if (! bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID))
+    return 0;
+
+  bgp->router_id.s_addr = 0;
+  bgp_config_unset (bgp, BGP_CONFIG_ROUTER_ID);
+
+  /* Clear peer router id configuration.  */
+  LIST_LOOP (bgp->peer, peer, nn)
+    {
+      peer->local_id.s_addr = 0;
+    }
+
+  /* Set router-id from interface's address. */
+  bgp_if_update_all ();
+
+  /* Reset all BGP sessions to use new router-id.  */
+  LIST_LOOP (bgp->peer, peer, nn)
+    {
+      if (peer->status == Established)
+	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+    }
+
+  return 0;
+}
+
+/* BGP's cluster-id control. */
+int
+bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
+{
+  struct peer *peer;
+  struct listnode *nn;
+
+  if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
+      && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
+    return 0;
+
+  IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
+  bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
+
+  /* Clear all IBGP peer. */
+  LIST_LOOP (bgp->peer, peer, nn)
+    {
+      if (peer_sort (peer) != BGP_PEER_IBGP)
+	continue;
+
+      if (peer->status == Established)
+	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+    }
+  return 0;
+}
+
+int
+bgp_cluster_id_unset (struct bgp *bgp)
+{
+  struct peer *peer;
+  struct listnode *nn;
+
+  if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
+    return 0;
+
+  bgp->cluster_id.s_addr = 0;
+  bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
+
+  /* Clear all IBGP peer. */
+  LIST_LOOP (bgp->peer, peer, nn)
+    {
+      if (peer_sort (peer) != BGP_PEER_IBGP)
+	continue;
+
+      if (peer->status == Established)
+	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+    }
+  return 0;
+}
+
+/* BGP timer configuration.  */
+int
+bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
+{
+  bgp->default_keepalive = (keepalive < holdtime / 3 
+			    ? keepalive : holdtime / 3);
+  bgp->default_holdtime = holdtime;
+
+  return 0;
+}
+
+int
+bgp_timers_unset (struct bgp *bgp)
+{
+  bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
+  bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
+
+  return 0;
+}
+
+/* BGP confederation configuration.  */
+int
+bgp_confederation_id_set (struct bgp *bgp, as_t as)
+{
+  struct peer *peer;
+  struct listnode *nn;
+  int already_confed;
+
+  if (as == 0)
+    return BGP_ERR_INVALID_AS;
+
+  /* Remember - were we doing confederation before? */
+  already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
+  bgp->confed_id = as;
+  bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
+
+  /* If we were doing confederation already, this is just an external
+     AS change.  Just Reset EBGP sessions, not CONFED sessions.  If we
+     were not doing confederation before, reset all EBGP sessions.  */
+  LIST_LOOP (bgp->peer, peer, nn)
+    {
+      /* We're looking for peers who's AS is not local or part of our
+	 confederation.  */
+      if (already_confed)
+	{
+	  if (peer_sort (peer) == BGP_PEER_EBGP)
+	    {
+	      peer->local_as = as;
+	      if (peer->status == Established)
+		bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+				 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+	      else
+		BGP_EVENT_ADD (peer, BGP_Stop);
+	    }
+	}
+      else
+	{
+	  /* Not doign confederation before, so reset every non-local
+	     session */
+	  if (peer_sort (peer) != BGP_PEER_IBGP)
+	    {
+	      /* Reset the local_as to be our EBGP one */
+	      if (peer_sort (peer) == BGP_PEER_EBGP)
+		peer->local_as = as;
+	      if (peer->status == Established)
+		bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+				 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+	      else
+		BGP_EVENT_ADD (peer, BGP_Stop);
+	    }
+	}
+    }
+  return 0;
+}
+
+int
+bgp_confederation_id_unset (struct bgp *bgp)
+{
+  struct peer *peer;
+  struct listnode *nn;
+
+  bgp->confed_id = 0;
+  bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
+      
+  LIST_LOOP (bgp->peer, peer, nn)
+    {
+      /* We're looking for peers who's AS is not local */
+      if (peer_sort (peer) != BGP_PEER_IBGP)
+	{
+	  peer->local_as = bgp->as;
+	  if (peer->status == Established)
+	    bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+			     BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+	  else
+	    BGP_EVENT_ADD (peer, BGP_Stop);
+	}
+    }
+  return 0;
+}
+
+/* Is an AS part of the confed or not? */
+int
+bgp_confederation_peers_check (struct bgp *bgp, as_t as)
+{
+  int i;
+
+  if (! bgp)
+    return 0;
+
+  for (i = 0; i < bgp->confed_peers_cnt; i++)
+    if (bgp->confed_peers[i] == as)
+      return 1;
+  
+  return 0;
+}
+
+/* Add an AS to the confederation set.  */
+int
+bgp_confederation_peers_add (struct bgp *bgp, as_t as)
+{
+  struct peer *peer;
+  struct listnode *nn;
+
+  if (! bgp)
+    return BGP_ERR_INVALID_BGP;
+
+  if (bgp->as == as)
+    return BGP_ERR_INVALID_AS;
+
+  if (bgp_confederation_peers_check (bgp, as))
+    return -1;
+
+  if (bgp->confed_peers)
+    bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST, 
+				  bgp->confed_peers,
+				  (bgp->confed_peers_cnt + 1) * sizeof (as_t));
+  else
+    bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST, 
+				 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
+
+  bgp->confed_peers[bgp->confed_peers_cnt] = as;
+  bgp->confed_peers_cnt++;
+
+  if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
+    {
+      LIST_LOOP (bgp->peer, peer, nn)
+	{
+	  if (peer->as == as)
+	    {
+	      peer->local_as = bgp->as;
+	      if (peer->status == Established)
+		bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+				 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+	      else
+	        BGP_EVENT_ADD (peer, BGP_Stop);
+	    }
+	}
+    }
+  return 0;
+}
+
+/* Delete an AS from the confederation set.  */
+int
+bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
+{
+  int i;
+  int j;
+  struct peer *peer;
+  struct listnode *nn;
+
+  if (! bgp)
+    return -1;
+
+  if (! bgp_confederation_peers_check (bgp, as))
+    return -1;
+
+  for (i = 0; i < bgp->confed_peers_cnt; i++)
+    if (bgp->confed_peers[i] == as)
+      for(j = i + 1; j < bgp->confed_peers_cnt; j++)
+	bgp->confed_peers[j - 1] = bgp->confed_peers[j];
+
+  bgp->confed_peers_cnt--;
+
+  if (bgp->confed_peers_cnt == 0)
+    {
+      if (bgp->confed_peers)
+	XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
+      bgp->confed_peers = NULL;
+    }
+  else
+    bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
+				  bgp->confed_peers,
+				  bgp->confed_peers_cnt * sizeof (as_t));
+
+  /* Now reset any peer who's remote AS has just been removed from the
+     CONFED */
+  if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
+    {
+      LIST_LOOP (bgp->peer, peer, nn)
+	{
+	  if (peer->as == as)
+	    {
+	      peer->local_as = bgp->confed_id;
+	      if (peer->status == Established)
+		bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+				 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+	      else
+		BGP_EVENT_ADD (peer, BGP_Stop);
+	    }
+	}
+    }
+
+  return 0;
+}
+
+/* Local preference configuration.  */
+int
+bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
+{
+  if (! bgp)
+    return -1;
+
+  bgp_config_set (bgp, BGP_CONFIG_DEFAULT_LOCAL_PREF);
+  bgp->default_local_pref = local_pref;
+
+  return 0;
+}
+
+int
+bgp_default_local_preference_unset (struct bgp *bgp)
+{
+  if (! bgp)
+    return -1;
+
+  bgp_config_unset (bgp, BGP_CONFIG_DEFAULT_LOCAL_PREF);
+  bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
+
+  return 0;
+}
+
+/* Peer comparison function for sorting.  */
+static int
+peer_cmp (struct peer *p1, struct peer *p2)
+{
+  return sockunion_cmp (&p1->su, &p2->su);
+}
+
+int
+peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
+{
+  return CHECK_FLAG (peer->af_flags[afi][safi], flag);
+}
+
+/* Reset all address family specific configuration.  */
+static void
+peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
+{
+  int i;
+  struct bgp_filter *filter;
+  char orf_name[BUFSIZ];
+
+  filter = &peer->filter[afi][safi];
+
+  /* Clear neighbor filter and route-map */
+  for (i = FILTER_IN; i < FILTER_MAX; i++)
+    {
+      if (filter->dlist[i].name)
+	{
+	  free (filter->dlist[i].name);
+	  filter->dlist[i].name = NULL;
+	}
+      if (filter->plist[i].name)
+	{
+	  free (filter->plist[i].name);
+	  filter->plist[i].name = NULL; 
+	}
+      if (filter->aslist[i].name)
+	{
+	  free (filter->aslist[i].name);
+	  filter->aslist[i].name = NULL;
+	}
+      if (filter->map[i].name)
+	{
+	  free (filter->map[i].name);
+	  filter->map[i].name = NULL;
+	}
+    }
+
+  /* Clear unsuppress map.  */
+  if (filter->usmap.name)
+    free (filter->usmap.name);
+  filter->usmap.name = NULL;
+  filter->usmap.map = NULL;
+
+  /* Clear neighbor's all address family flags.  */
+  peer->af_flags[afi][safi] = 0;
+
+  /* Clear neighbor's all address family sflags. */
+  peer->af_sflags[afi][safi] = 0;
+
+  /* Clear neighbor's all address family capabilities. */
+  peer->af_cap[afi][safi] = 0;
+
+  /* Clear ORF info */
+  peer->orf_plist[afi][safi] = NULL;
+  sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
+  prefix_bgp_orf_remove_all (orf_name);
+
+  /* Set default neighbor send-community.  */
+  if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
+    {
+      SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
+      SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
+    }
+
+  /* Clear neighbor default_originate_rmap */
+  if (peer->default_rmap[afi][safi].name)
+    free (peer->default_rmap[afi][safi].name);
+  peer->default_rmap[afi][safi].name = NULL;
+  peer->default_rmap[afi][safi].map = NULL;
+
+  /* Clear neighbor maximum-prefix */
+  peer->pmax[afi][safi] = 0;
+}
+
+/* peer global config reset */
+void
+peer_global_config_reset (struct peer *peer)
+{
+  peer->weight = 0;
+  peer->change_local_as = 0;
+  peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
+  if (peer->update_source)
+    {
+      sockunion_free (peer->update_source);
+      peer->update_source = NULL;
+    }
+  if (peer->update_if)
+    {
+      XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
+      peer->update_if = NULL;
+    }
+
+  if (peer_sort (peer) == BGP_PEER_IBGP)
+    peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
+  else
+    peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
+
+  peer->flags = 0;
+  peer->config = 0;
+  peer->holdtime = 0;
+  peer->keepalive = 0;
+  peer->connect = 0;
+  peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
+}
+
+/* Check peer's AS number and determin is this peer IBGP or EBGP */
+int
+peer_sort (struct peer *peer)
+{
+  struct bgp *bgp;
+
+  bgp = peer->bgp;
+
+  /* Peer-group */
+  if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    {
+      if (peer->as)
+	return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
+      else
+	{
+	  struct peer *peer1;
+	  peer1 = listnode_head (peer->group->peer);
+	  if (peer1)
+	    return (peer1->local_as == peer1->as 
+		    ? BGP_PEER_IBGP : BGP_PEER_EBGP);
+	} 
+      return BGP_PEER_INTERNAL;
+    }
+
+  /* Normal peer */
+  if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
+    {
+      if (peer->local_as == 0)
+	return BGP_PEER_INTERNAL;
+
+      if (peer->local_as == peer->as)
+	{
+	  if (peer->local_as == bgp->confed_id)
+	    return BGP_PEER_EBGP;
+	  else
+	    return BGP_PEER_IBGP;
+	}
+
+      if (bgp_confederation_peers_check (bgp, peer->as))
+	return BGP_PEER_CONFED;
+
+      return BGP_PEER_EBGP;
+    }
+  else
+    {
+      return (peer->local_as == 0
+	      ? BGP_PEER_INTERNAL : peer->local_as == peer->as
+	      ? BGP_PEER_IBGP : BGP_PEER_EBGP);
+    }
+}
+
+/* Allocate new peer object.  */
+static struct peer *
+peer_new ()
+{
+  afi_t afi;
+  safi_t safi;
+  struct peer *peer;
+  struct servent *sp;
+
+  /* Allocate new peer. */
+  peer = XMALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
+  memset (peer, 0, sizeof (struct peer));
+
+  /* Set default value. */
+  peer->fd = -1;
+  peer->v_start = BGP_INIT_START_TIMER;
+  peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
+  peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
+  peer->status = Idle;
+  peer->ostatus = Idle;
+  peer->version = BGP_VERSION_4;
+  peer->weight = 0;
+
+  /* Set default flags.  */
+  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+      {
+	if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
+	  {
+	    SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
+	    SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
+	  }
+	peer->orf_plist[afi][safi] = NULL;
+      }
+  SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
+
+  /* Create buffers.  */
+  peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
+  peer->obuf = stream_fifo_new ();
+  peer->work = stream_new (BGP_MAX_PACKET_SIZE);
+
+  bgp_sync_init (peer);
+
+  /* Get service port number.  */
+  sp = getservbyname ("bgp", "tcp");
+  peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
+
+  return peer;
+}
+
+/* Create new BGP peer.  */
+struct peer *
+peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
+	     as_t remote_as, afi_t afi, safi_t safi)
+{
+  int active;
+  struct peer *peer;
+  char buf[SU_ADDRSTRLEN];
+
+  peer = peer_new ();
+  peer->bgp = bgp;
+  peer->su = *su;
+  peer->local_as = local_as;
+  peer->as = remote_as;
+  peer->local_id = bgp->router_id;
+  peer->v_holdtime = bgp->default_holdtime;
+  peer->v_keepalive = bgp->default_keepalive;
+  if (peer_sort (peer) == BGP_PEER_IBGP)
+    peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
+  else
+    peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
+  listnode_add_sort (bgp->peer, peer);
+
+  active = peer_active (peer);
+
+  if (afi && safi)
+    peer->afc[afi][safi] = 1;
+
+  /* Last read time set */
+  peer->readtime = time (NULL);
+
+  /* Default TTL set. */
+  peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
+
+  /* Make peer's address string. */
+  sockunion2str (su, buf, SU_ADDRSTRLEN);
+  peer->host = strdup (buf);
+
+  /* Set up peer's events and timers. */
+  if (! active && peer_active (peer))
+    bgp_timer_set (peer);
+
+  return peer;
+}
+
+/* Make accept BGP peer.  Called from bgp_accept (). */
+struct peer *
+peer_create_accept (struct bgp *bgp)
+{
+  struct peer *peer;
+
+  peer = peer_new ();
+  peer->bgp = bgp;
+  listnode_add_sort (bgp->peer, peer);
+
+  return peer;
+}
+
+/* Change peer's AS number.  */
+void
+peer_as_change (struct peer *peer, as_t as)
+{
+  int type;
+
+  /* Stop peer. */
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    {
+      if (peer->status == Established)
+	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+      else
+	BGP_EVENT_ADD (peer, BGP_Stop);
+    }
+  type = peer_sort (peer);
+  peer->as = as;
+
+  /* Advertisement-interval reset */
+  if (peer_sort (peer) == BGP_PEER_IBGP)
+    peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
+  else
+    peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
+
+  /* TTL reset */
+  if (peer_sort (peer) == BGP_PEER_IBGP)
+    peer->ttl = 255;
+  else if (type == BGP_PEER_IBGP)
+    peer->ttl = 1;
+
+  /* reflector-client reset */
+  if (peer_sort (peer) != BGP_PEER_IBGP)
+    {
+      UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
+		  PEER_FLAG_REFLECTOR_CLIENT);
+      UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
+		  PEER_FLAG_REFLECTOR_CLIENT);
+      UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
+		  PEER_FLAG_REFLECTOR_CLIENT);
+      UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
+		  PEER_FLAG_REFLECTOR_CLIENT);
+      UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
+		  PEER_FLAG_REFLECTOR_CLIENT);
+    }
+
+  /* local-as reset */
+  if (peer_sort (peer) != BGP_PEER_EBGP)
+    {
+      peer->change_local_as = 0;
+      UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
+    }
+}
+
+/* If peer does not exist, create new one.  If peer already exists,
+   set AS number to the peer.  */
+int
+peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
+		afi_t afi, safi_t safi)
+{
+  struct peer *peer;
+  as_t local_as;
+
+  peer = peer_lookup (bgp, su);
+
+  if (peer)
+    {
+      /* When this peer is a member of peer-group.  */
+      if (peer->group)
+	{
+	  if (peer->group->conf->as)
+	    {
+	      /* Return peer group's AS number.  */
+	      *as = peer->group->conf->as;
+	      return BGP_ERR_PEER_GROUP_MEMBER;
+	    }
+	  if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
+	    {
+	      if (bgp->as != *as)
+		{
+		  *as = peer->as;
+		  return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
+		}
+	    }
+	  else
+	    {
+	      if (bgp->as == *as)
+		{
+		  *as = peer->as;
+		  return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
+		}
+	    }
+	}
+
+      /* Existing peer's AS number change. */
+      if (peer->as != *as)
+	peer_as_change (peer, *as);
+    }
+  else
+    {
+
+      /* If the peer is not part of our confederation, and its not an
+	 iBGP peer then spoof the source AS */
+      if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
+	  && ! bgp_confederation_peers_check (bgp, *as) 
+	  && bgp->as != *as)
+	local_as = bgp->confed_id;
+      else
+	local_as = bgp->as;
+      
+      /* If this is IPv4 unicast configuration and "no bgp default
+         ipv4-unicast" is specified. */
+
+      if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
+	  && afi == AFI_IP && safi == SAFI_UNICAST)
+	peer = peer_create (su, bgp, local_as, *as, 0, 0); 
+      else
+	peer = peer_create (su, bgp, local_as, *as, afi, safi); 
+    }
+
+  return 0;
+}
+
+/* Activate the peer or peer group for specified AFI and SAFI.  */
+int
+peer_activate (struct peer *peer, afi_t afi, safi_t safi)
+{
+  int active;
+
+  if (peer->afc[afi][safi])
+    return 0;
+
+  /* Activate the address family configuration. */
+  if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    peer->afc[afi][safi] = 1;
+  else
+    {
+      active = peer_active (peer);
+
+      peer->afc[afi][safi] = 1;
+
+      if (! active && peer_active (peer))
+	bgp_timer_set (peer);
+      else
+	{
+	  if (peer->status == Established)
+	    {
+	      if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
+		{
+		  peer->afc_adv[afi][safi] = 1;
+		  bgp_capability_send (peer, afi, safi,
+				       CAPABILITY_CODE_MP,
+				       CAPABILITY_ACTION_SET);
+		  if (peer->afc_recv[afi][safi])
+		    {
+		      peer->afc_nego[afi][safi] = 1;
+		      bgp_announce_route (peer, afi, safi);
+		    }
+		}
+	      else
+		bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+				 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+	    }
+	}
+    }
+  return 0;
+}
+
+int
+peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
+{
+  struct peer_group *group;
+  struct peer *peer1;
+  struct listnode *nn;
+
+  if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    {
+      group = peer->group;
+
+      LIST_LOOP (group->peer, peer1, nn)
+	{
+	  if (peer1->af_group[afi][safi])
+	    return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
+	}
+    }
+  else
+    {
+      if (peer->af_group[afi][safi])
+	return BGP_ERR_PEER_BELONGS_TO_GROUP;
+    }
+
+  if (! peer->afc[afi][safi])
+    return 0;
+
+  /* De-activate the address family configuration. */
+  peer->afc[afi][safi] = 0;
+  peer_af_flag_reset (peer, afi, safi);
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    {  
+      if (peer->status == Established)
+	{
+	  if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
+	    {
+	      peer->afc_adv[afi][safi] = 0;
+	      peer->afc_nego[afi][safi] = 0;
+
+	      if (peer_active_nego (peer))
+		{
+		  bgp_capability_send (peer, afi, safi,
+				       CAPABILITY_CODE_MP,
+				       CAPABILITY_ACTION_UNSET);
+		  bgp_clear_route (peer, afi, safi);
+		  peer->pcount[afi][safi] = 0;
+		}
+	      else
+		bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+				 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+	    }
+	  else
+	    bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+			     BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+	}
+    }
+  return 0;
+}
+
+/* Delete peer from confguration. */
+int
+peer_delete (struct peer *peer)
+{
+  int i;
+  afi_t afi;
+  safi_t safi;
+  struct bgp *bgp;
+  struct bgp_filter *filter;
+
+  bgp = peer->bgp;
+
+  /* If this peer belongs to peer group.  Clearn up the
+     relationship.  */
+  if (peer->group)
+    {
+      listnode_delete (peer->group->peer, peer);
+      peer->group = NULL;
+    }
+
+  /* Withdraw all information from routing table.  We can not use
+     BGP_EVENT_ADD (peer, BGP_Stop) at here.  Because the event is
+     executed after peer structure is deleted. */
+  bgp_stop (peer);
+  bgp_fsm_change_status (peer, Idle);
+
+  /* Stop all timers. */
+  BGP_TIMER_OFF (peer->t_start);
+  BGP_TIMER_OFF (peer->t_connect);
+  BGP_TIMER_OFF (peer->t_holdtime);
+  BGP_TIMER_OFF (peer->t_keepalive);
+  BGP_TIMER_OFF (peer->t_asorig);
+  BGP_TIMER_OFF (peer->t_routeadv);
+
+  /* Delete from all peer list. */
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    listnode_delete (bgp->peer, peer);
+
+  /* Buffer.  */
+  if (peer->ibuf)
+    stream_free (peer->ibuf);
+
+  if (peer->obuf)
+    stream_fifo_free (peer->obuf);
+
+  if (peer->work)
+    stream_free (peer->work);
+
+  /* Free allocated host character. */
+  if (peer->host)
+    free (peer->host);
+
+  /* Local and remote addresses. */
+  if (peer->su_local)
+    XFREE (MTYPE_TMP, peer->su_local);
+  if (peer->su_remote)
+    XFREE (MTYPE_TMP, peer->su_remote);
+
+  /* Peer description string.  */
+  if (peer->desc)
+    XFREE (MTYPE_TMP, peer->desc);
+
+  bgp_sync_delete (peer);
+
+  /* Free filter related memory.  */
+  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+      {
+	filter = &peer->filter[afi][safi];
+
+	for (i = FILTER_IN; i < FILTER_MAX; i++)
+	  {
+	    if (filter->dlist[i].name)
+	      free (filter->dlist[i].name);
+	    if (filter->plist[i].name)
+	      free (filter->plist[i].name);
+	    if (filter->aslist[i].name)
+	      free (filter->aslist[i].name);
+	    if (filter->map[i].name)
+	      free (filter->map[i].name);
+	  }
+
+	if (filter->usmap.name)
+	  free (filter->usmap.name);
+
+	if (peer->default_rmap[afi][safi].name)
+	  free (peer->default_rmap[afi][safi].name);
+      }
+
+  /* Update source configuration.  */
+  if (peer->update_source)
+    {
+      sockunion_free (peer->update_source);
+      peer->update_source = NULL;
+    }
+  if (peer->update_if)
+    {
+      XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
+      peer->update_if = NULL;
+    }
+
+  /* Free peer structure. */
+  XFREE (MTYPE_BGP_PEER, peer);
+
+  return 0;
+}
+
+int
+peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
+{
+  return strcmp (g1->name, g2->name);
+}
+
+/* If peer is configured at least one address family return 1. */
+int
+peer_group_active (struct peer *peer)
+{
+  if (peer->af_group[AFI_IP][SAFI_UNICAST]
+      || peer->af_group[AFI_IP][SAFI_MULTICAST]
+      || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
+      || peer->af_group[AFI_IP6][SAFI_UNICAST]
+      || peer->af_group[AFI_IP6][SAFI_MULTICAST])
+    return 1;
+  return 0;
+}
+
+/* Peer group cofiguration. */
+static struct peer_group *
+peer_group_new ()
+{
+  return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
+					sizeof (struct peer_group));
+}
+
+void
+peer_group_free (struct peer_group *group)
+{
+  XFREE (MTYPE_PEER_GROUP, group);
+}
+
+struct peer_group *
+peer_group_lookup (struct bgp *bgp, char *name)
+{
+  struct peer_group *group;
+  struct listnode *nn;
+
+  LIST_LOOP (bgp->group, group, nn)
+    {
+      if (strcmp (group->name, name) == 0)
+	return group;
+    }
+  return NULL;
+}
+
+struct peer_group *
+peer_group_get (struct bgp *bgp, char *name)
+{
+  struct peer_group *group;
+
+  group = peer_group_lookup (bgp, name);
+  if (group)
+    return group;
+
+  group = peer_group_new ();
+  group->bgp = bgp;
+  group->name = strdup (name);
+  group->peer = list_new ();
+  group->conf = peer_new ();
+  if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
+    group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
+  group->conf->host = strdup (name);
+  group->conf->bgp = bgp;
+  group->conf->group = group;
+  group->conf->as = 0; 
+  group->conf->ttl = 1;
+  group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
+  UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
+  UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
+  group->conf->keepalive = 0;
+  group->conf->holdtime = 0;
+  group->conf->connect = 0;
+  SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
+  listnode_add_sort (bgp->group, group);
+
+  return 0;
+}
+
+void 
+peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
+			     afi_t afi, safi_t safi)
+{
+  int in = FILTER_IN;
+  int out = FILTER_OUT;
+  struct peer *conf;
+  struct bgp_filter *pfilter;
+  struct bgp_filter *gfilter;
+
+  conf = group->conf;
+  pfilter = &peer->filter[afi][safi];
+  gfilter = &conf->filter[afi][safi];
+
+  /* remote-as */
+  if (conf->as)
+    peer->as = conf->as;
+
+  /* remote-as */
+  if (conf->change_local_as)
+    peer->change_local_as = conf->change_local_as;
+
+  /* TTL */
+  peer->ttl = conf->ttl;
+
+  /* Weight */
+  peer->weight = conf->weight;
+
+  /* peer flags apply */
+  peer->flags = conf->flags;
+  /* peer af_flags apply */
+  peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
+  /* peer config apply */
+  peer->config = conf->config;
+
+  /* peer timers apply */
+  peer->holdtime = conf->holdtime;
+  peer->keepalive = conf->keepalive;
+  peer->connect = conf->connect;
+  if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
+    peer->v_connect = conf->connect;
+  else
+    peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
+
+  /* advertisement-interval reset */
+  if (peer_sort (peer) == BGP_PEER_IBGP)
+    peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
+  else
+    peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
+
+  /* maximum-prefix */
+  peer->pmax[afi][safi] = conf->pmax[afi][safi];
+
+  /* allowas-in */
+  peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
+
+  /* default-originate route-map */
+  if (conf->default_rmap[afi][safi].name)
+    {
+      if (peer->default_rmap[afi][safi].name)
+	free (peer->default_rmap[afi][safi].name);
+      peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
+      peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
+    }
+
+  /* update-source apply */
+  if (conf->update_source)
+    {
+      if (peer->update_source)
+	sockunion_free (peer->update_source);
+      if (peer->update_if)
+	{
+	  XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
+	  peer->update_if = NULL;
+	}
+      peer->update_source = sockunion_dup (conf->update_source);
+    }
+  else if (conf->update_if)
+    {
+      if (peer->update_if)
+	XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
+      if (peer->update_source)
+	{
+	  sockunion_free (peer->update_source);
+	  peer->update_source = NULL;
+	}
+      peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
+    }
+
+  /* inbound filter apply */
+  if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
+    {
+      if (pfilter->dlist[in].name)
+	free (pfilter->dlist[in].name);
+      pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
+      pfilter->dlist[in].alist = gfilter->dlist[in].alist;
+    }
+  if (gfilter->plist[in].name && ! pfilter->plist[in].name)
+    {
+      if (pfilter->plist[in].name)
+	free (pfilter->plist[in].name);
+      pfilter->plist[in].name = strdup (gfilter->plist[in].name);
+      pfilter->plist[in].plist = gfilter->plist[in].plist;
+    }
+  if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
+    {
+      if (pfilter->aslist[in].name)
+	free (pfilter->aslist[in].name);
+      pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
+      pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
+    }
+  if (gfilter->map[in].name && ! pfilter->map[in].name)
+    {
+      if (pfilter->map[in].name)
+	free (pfilter->map[in].name);
+      pfilter->map[in].name = strdup (gfilter->map[in].name);
+      pfilter->map[in].map = gfilter->map[in].map;
+    }
+
+  /* outbound filter apply */
+  if (gfilter->dlist[out].name)
+    {
+      if (pfilter->dlist[out].name)
+	free (pfilter->dlist[out].name);
+      pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
+      pfilter->dlist[out].alist = gfilter->dlist[out].alist;
+    }
+  else
+    {
+      if (pfilter->dlist[out].name)
+	free (pfilter->dlist[out].name);
+      pfilter->dlist[out].name = NULL;
+      pfilter->dlist[out].alist = NULL;
+    }
+  if (gfilter->plist[out].name)
+    {
+      if (pfilter->plist[out].name)
+	free (pfilter->plist[out].name);
+      pfilter->plist[out].name = strdup (gfilter->plist[out].name);
+      pfilter->plist[out].plist = gfilter->plist[out].plist;
+    }
+  else
+    {
+      if (pfilter->plist[out].name)
+	free (pfilter->plist[out].name);
+      pfilter->plist[out].name = NULL;
+      pfilter->plist[out].plist = NULL;
+    }
+  if (gfilter->aslist[out].name)
+    {
+      if (pfilter->aslist[out].name)
+	free (pfilter->aslist[out].name);
+      pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
+      pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
+    }
+  else
+    {
+      if (pfilter->aslist[out].name)
+	free (pfilter->aslist[out].name);
+      pfilter->aslist[out].name = NULL;
+      pfilter->aslist[out].aslist = NULL;
+    }
+  if (gfilter->map[out].name)
+    {
+      if (pfilter->map[out].name)
+	free (pfilter->map[out].name);
+      pfilter->map[out].name = strdup (gfilter->map[out].name);
+      pfilter->map[out].map = gfilter->map[out].map;
+    }
+  else
+    {
+      if (pfilter->map[out].name)
+	free (pfilter->map[out].name);
+      pfilter->map[out].name = NULL;
+      pfilter->map[out].map = NULL;
+    }
+
+  if (gfilter->usmap.name)
+    {
+      if (pfilter->usmap.name)
+	free (pfilter->usmap.name);
+      pfilter->usmap.name = strdup (gfilter->usmap.name);
+      pfilter->usmap.map = gfilter->usmap.map;
+    }
+  else
+    {
+      if (pfilter->usmap.name)
+	free (pfilter->usmap.name);
+      pfilter->usmap.name = NULL;
+      pfilter->usmap.map = NULL;
+    }
+} 
+
+/* Peer group's remote AS configuration.  */
+int
+peer_group_remote_as (struct bgp *bgp, char *group_name, as_t *as)
+{
+  struct peer_group *group;
+  struct peer *peer;
+  struct listnode *nn;
+
+  group = peer_group_lookup (bgp, group_name);
+  if (! group)
+    return -1;
+
+  if (group->conf->as == *as)
+    return 0;
+
+  /* When we setup peer-group AS number all peer group member's AS
+     number must be updated to same number.  */
+  peer_as_change (group->conf, *as);
+
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      if (peer->as != *as)
+	peer_as_change (peer, *as);
+    }
+
+  return 0;
+}
+
+int
+peer_group_delete (struct peer_group *group)
+{
+  struct bgp *bgp;
+  struct peer *peer;
+  struct listnode *nn;
+
+  bgp = group->bgp;
+
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      peer->group = NULL;
+      peer_delete (peer);
+    }
+  list_delete (group->peer);
+
+  free (group->name);
+  group->name = NULL;
+
+  group->conf->group = NULL;
+  peer_delete (group->conf);
+
+  /* Delete from all peer_group list. */
+  listnode_delete (bgp->group, group);
+
+  peer_group_free (group);
+
+  return 0;
+}
+
+int
+peer_group_remote_as_delete (struct peer_group *group)
+{
+  struct peer *peer;
+  struct listnode *nn;
+
+  if (! group->conf->as)
+    return 0;
+
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      peer->group = NULL;
+      peer_delete (peer);
+    }
+  list_delete_all_node (group->peer);
+
+  group->conf->as = 0;
+
+  return 0;
+}
+
+/* Bind specified peer to peer group.  */
+int
+peer_group_bind (struct bgp *bgp, union sockunion *su,
+		 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
+{
+  struct peer *peer;
+  int first_member = 0;
+
+  /* Check peer group's address family.  */
+  if (! group->conf->afc[afi][safi])
+    return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
+
+  /* Lookup the peer.  */
+  peer = peer_lookup (bgp, su);
+
+  /* Create a new peer. */
+  if (! peer)
+    {
+      if (! group->conf->as)
+	return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
+
+      peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
+      peer->group = group;
+      peer->af_group[afi][safi] = 1;
+      listnode_add (group->peer, peer);
+      peer_group2peer_config_copy (group, peer, afi, safi);
+
+      return 0;
+    }
+
+  /* When the peer already belongs to peer group, check the consistency.  */
+  if (peer->af_group[afi][safi])
+    {
+      if (strcmp (peer->group->name, group->name) != 0)
+	return BGP_ERR_PEER_GROUP_CANT_CHANGE;
+
+      return 0;
+    }
+
+  /* Check current peer group configuration.  */
+  if (peer_group_active (peer)
+      && strcmp (peer->group->name, group->name) != 0)
+    return BGP_ERR_PEER_GROUP_MISMATCH;
+
+  if (! group->conf->as)
+    {
+      if (peer_sort (group->conf) != BGP_PEER_INTERNAL
+	  && peer_sort (group->conf) != peer_sort (peer))
+	{
+	  if (as)
+	    *as = peer->as;
+	  return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
+	}
+
+      if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
+	first_member = 1;
+    }
+
+  peer->af_group[afi][safi] = 1;
+  peer->afc[afi][safi] = 1;
+  if (! peer->group)
+    {
+      peer->group = group;
+      listnode_add (group->peer, peer);
+    }
+
+  if (first_member)
+    {
+      /* Advertisement-interval reset */
+      if (peer_sort (group->conf) == BGP_PEER_IBGP)
+	group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
+      else
+	group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
+
+      /* ebgp-multihop reset */
+      if (peer_sort (group->conf) == BGP_PEER_IBGP)
+	group->conf->ttl = 255;
+
+      /* local-as reset */
+      if (peer_sort (group->conf) != BGP_PEER_EBGP)
+	{
+	  group->conf->change_local_as = 0;
+	  UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
+	}
+    }
+  peer_group2peer_config_copy (group, peer, afi, safi);
+
+  if (peer->status == Established)
+    bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+		     BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+  else
+    BGP_EVENT_ADD (peer, BGP_Stop);
+
+  return 0;
+}
+
+int
+peer_group_unbind (struct bgp *bgp, struct peer *peer,
+		   struct peer_group *group, afi_t afi, safi_t safi)
+{
+  if (! peer->af_group[afi][safi])
+      return 0;
+
+  if (group != peer->group)
+    return BGP_ERR_PEER_GROUP_MISMATCH;
+
+  peer->af_group[afi][safi] = 0;
+  peer->afc[afi][safi] = 0;
+  peer_af_flag_reset (peer, afi, safi);
+
+  if (! peer_group_active (peer))
+    {
+      listnode_delete (group->peer, peer);
+      peer->group = NULL;
+      if (group->conf->as)
+	{
+	  peer_delete (peer);
+	  return 0;
+	}
+      peer_global_config_reset (peer);
+    }
+
+  if (peer->status == Established)
+    bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+		     BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+  else
+    BGP_EVENT_ADD (peer, BGP_Stop);
+
+  return 0;
+}
+
+/* BGP instance creation by `router bgp' commands. */
+struct bgp *
+bgp_create (as_t *as, char *name)
+{
+  struct bgp *bgp;
+  afi_t afi;
+  safi_t safi;
+
+  bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp));
+
+  bgp->peer_self = peer_new ();
+  bgp->peer_self->host = "Static announcement";
+
+  bgp->peer = list_new ();
+  bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
+
+  bgp->group = list_new ();
+  bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
+
+  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+      {
+	bgp->route[afi][safi] = bgp_table_init ();
+	bgp->aggregate[afi][safi] = bgp_table_init ();
+	bgp->rib[afi][safi] = bgp_table_init ();
+      }
+
+  bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
+  bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
+  bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
+
+  bgp->as = *as;
+
+  if (name)
+    bgp->name = strdup (name);
+
+  return bgp;
+}
+
+/* Return first entry of BGP. */
+struct bgp *
+bgp_get_default ()
+{
+  if (bm->bgp->head)
+    return bm->bgp->head->data;
+  return NULL;
+}
+
+/* Lookup BGP entry. */
+struct bgp *
+bgp_lookup (as_t as, char *name)
+{
+  struct bgp *bgp;
+  struct listnode *nn;
+
+  LIST_LOOP (bm->bgp, bgp, nn)
+    if (bgp->as == as
+	&& ((bgp->name == NULL && name == NULL) 
+	    || (bgp->name && name && strcmp (bgp->name, name) == 0)))
+      return bgp;
+  return NULL;
+}
+
+/* Lookup BGP structure by view name. */
+struct bgp *
+bgp_lookup_by_name (char *name)
+{
+  struct bgp *bgp;
+  struct listnode *nn;
+
+  LIST_LOOP (bm->bgp, bgp, nn)
+    if ((bgp->name == NULL && name == NULL)
+	|| (bgp->name && name && strcmp (bgp->name, name) == 0))
+      return bgp;
+  return NULL;
+}
+
+/* Called from VTY commands. */
+int
+bgp_get (struct bgp **bgp_val, as_t *as, char *name)
+{
+  struct bgp *bgp;
+
+  /* Multiple instance check. */
+  if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
+    {
+      if (name)
+	bgp = bgp_lookup_by_name (name);
+      else
+	bgp = bgp_get_default ();
+
+      /* Already exists. */
+      if (bgp)
+	{
+          if (bgp->as != *as)
+	    {
+	      *as = bgp->as;
+	      return BGP_ERR_INSTANCE_MISMATCH;
+	    }
+	  *bgp_val = bgp;
+	  return 0;
+	}
+    }
+  else
+    {
+      /* BGP instance name can not be specified for single instance.  */
+      if (name)
+	return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
+
+      /* Get default BGP structure if exists. */
+      bgp = bgp_get_default ();
+
+      if (bgp)
+	{
+	  if (bgp->as != *as)
+	    {
+	      *as = bgp->as;
+	      return BGP_ERR_AS_MISMATCH;
+	    }
+	  *bgp_val = bgp;
+	  return 0;
+	}
+    }
+
+  bgp = bgp_create (as, name);
+  listnode_add (bm->bgp, bgp);
+  bgp_if_update_all ();
+  *bgp_val = bgp;
+
+  return 0;
+}
+
+/* Delete BGP instance. */
+int
+bgp_delete (struct bgp *bgp)
+{
+  struct peer *peer;
+  struct listnode *nn;
+  struct listnode *next;
+  afi_t afi;
+  safi_t safi;
+  int i;
+
+  /* Delete static route. */
+  bgp_static_delete (bgp);
+
+  /* Unset redistribution. */
+  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+    for (i = 0; i < ZEBRA_ROUTE_MAX; i++) 
+      if (i != ZEBRA_ROUTE_BGP)
+	bgp_redistribute_unset (bgp, afi, i);
+
+  bgp->group->del = (void (*)(void *)) peer_group_delete;
+  list_delete (bgp->group);
+
+  for (nn = bgp->peer->head; nn; nn = next)
+    {
+      peer = nn->data;
+      next = nn->next;
+      peer_delete (peer);
+    }
+
+  listnode_delete (bm->bgp, bgp);
+
+  if (bgp->name)
+    free (bgp->name);
+  
+  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+      {
+	if (bgp->route[afi][safi])
+	  XFREE (MTYPE_ROUTE_TABLE, bgp->route[afi][safi]);
+	if (bgp->aggregate[afi][safi])
+	  XFREE (MTYPE_ROUTE_TABLE,bgp->aggregate[afi][safi]) ;
+	if (bgp->rib[afi][safi])
+	  XFREE (MTYPE_ROUTE_TABLE,bgp->rib[afi][safi]);
+      }
+  XFREE (MTYPE_BGP, bgp);
+
+  return 0;
+}
+
+struct peer *
+peer_lookup (struct bgp *bgp, union sockunion *su)
+{
+  struct peer *peer;
+  struct listnode *nn;
+
+  if (! bgp)
+    bgp = bgp_get_default ();
+
+  if (! bgp)
+    return NULL;
+  
+  LIST_LOOP (bgp->peer, peer, nn)
+    {
+      if (sockunion_same (&peer->su, su)
+	  && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
+	return peer;
+    }
+  return NULL;
+}
+
+struct peer *
+peer_lookup_with_open (union sockunion *su, as_t remote_as,
+		       struct in_addr *remote_id, int *as)
+{
+  struct peer *peer;
+  struct listnode *nn;
+  struct bgp *bgp;
+
+  bgp = bgp_get_default ();
+  if (! bgp)
+    return NULL;
+
+  LIST_LOOP (bgp->peer, peer, nn)
+    {
+      if (sockunion_same (&peer->su, su)
+	  && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
+	{
+	  if (peer->as == remote_as
+	      && peer->remote_id.s_addr == remote_id->s_addr)
+	    return peer;
+	  if (peer->as == remote_as)
+	    *as = 1;
+	}
+    }
+  LIST_LOOP (bgp->peer, peer, nn)
+    {
+      if (sockunion_same (&peer->su, su)
+	  &&  ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
+	{
+	  if (peer->as == remote_as
+	      && peer->remote_id.s_addr == 0)
+	    return peer;
+	  if (peer->as == remote_as)
+	    *as = 1;
+	}
+    }
+  return NULL;
+}
+
+/* If peer is configured at least one address family return 1. */
+int
+peer_active (struct peer *peer)
+{
+  if (peer->afc[AFI_IP][SAFI_UNICAST]
+      || peer->afc[AFI_IP][SAFI_MULTICAST]
+      || peer->afc[AFI_IP][SAFI_MPLS_VPN]
+      || peer->afc[AFI_IP6][SAFI_UNICAST]
+      || peer->afc[AFI_IP6][SAFI_MULTICAST])
+    return 1;
+  return 0;
+}
+
+/* If peer is negotiated at least one address family return 1. */
+int
+peer_active_nego (struct peer *peer)
+{
+  if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
+      || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
+      || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
+      || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
+      || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
+    return 1;
+  return 0;
+}
+
+/* peer_flag_change_type. */
+enum peer_change_type
+{
+  peer_change_none,
+  peer_change_reset,
+  peer_change_reset_in,
+  peer_change_reset_out,
+};
+
+void
+peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
+		    enum peer_change_type type)
+{
+  if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    return;
+
+  if (type == peer_change_reset)
+    bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+		     BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+  else if (type == peer_change_reset_in)
+    {
+      if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
+	  || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
+	bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
+      else
+	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+    }
+  else if (type == peer_change_reset_out)
+    bgp_announce_route (peer, afi, safi);
+}
+
+struct peer_flag_action
+{
+  /* Peer's flag.  */
+  u_int32_t flag;
+
+  /* This flag can be set for peer-group member.  */
+  u_char not_for_member;
+
+  /* Action when the flag is changed.  */
+  enum peer_change_type type;
+};
+
+struct peer_flag_action peer_flag_action_list[] = 
+  {
+    { PEER_FLAG_PASSIVE,                  0, peer_change_reset },
+    { PEER_FLAG_SHUTDOWN,                 0, peer_change_reset },
+    { PEER_FLAG_DONT_CAPABILITY,          0, peer_change_none },
+    { PEER_FLAG_OVERRIDE_CAPABILITY,      0, peer_change_none },
+    { PEER_FLAG_STRICT_CAP_MATCH,         0, peer_change_none },
+    { PEER_FLAG_NO_ROUTE_REFRESH_CAP,     0, peer_change_reset },
+    { PEER_FLAG_DYNAMIC_CAPABILITY,       0, peer_change_reset },
+    { PEER_FLAG_ENFORCE_MULTIHOP,         0, peer_change_reset },
+    { 0, 0, 0 }
+  };
+
+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 },
+    { PEER_FLAG_SEND_EXT_COMMUNITY,       1, peer_change_reset_out },
+    { PEER_FLAG_SOFT_RECONFIG,            0, peer_change_reset_in },
+    { PEER_FLAG_REFLECTOR_CLIENT,         1, peer_change_reset },
+    { PEER_FLAG_RSERVER_CLIENT,           1, peer_change_reset },
+    { PEER_FLAG_AS_PATH_UNCHANGED,        1, peer_change_reset_out },
+    { PEER_FLAG_NEXTHOP_UNCHANGED,        1, peer_change_reset_out },
+    { PEER_FLAG_MED_UNCHANGED,            1, peer_change_reset_out },
+    { PEER_FLAG_REMOVE_PRIVATE_AS,        1, peer_change_reset_out },
+    { PEER_FLAG_ALLOWAS_IN,               0, peer_change_reset_in },
+    { PEER_FLAG_ORF_PREFIX_SM,            1, peer_change_reset },
+    { PEER_FLAG_ORF_PREFIX_RM,            1, peer_change_reset },
+    { 0, 0, 0 }
+  };
+
+/* Proper action set. */
+int
+peer_flag_action_set (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;
+
+  /* Check peer's frag action.  */
+  for (i = 0; i < size; i++)
+    {
+      match = &action_list[i];
+
+      if (match->flag == 0)
+	break;
+
+      if (match->flag & flag)
+	{
+	  found = 1;
+
+	  if (match->type == peer_change_reset_in)
+	    reset_in = 1;
+	  if (match->type == peer_change_reset_out)
+	    reset_out = 1;
+	  if (match->type == peer_change_reset)
+	    {
+	      reset_in = 1;
+	      reset_out = 1;
+	    }
+	  if (match->not_for_member)
+	    action->not_for_member = 1;
+	}
+    }
+
+  /* Set peer clear type.  */
+  if (reset_in && reset_out)
+    action->type = peer_change_reset;
+  else if (reset_in)
+    action->type = peer_change_reset_in;
+  else if (reset_out)
+    action->type = peer_change_reset_out;
+  else
+    action->type = peer_change_none;
+
+  return found;
+}
+
+void
+peer_flag_modify_action (struct peer *peer, u_int32_t flag)
+{
+  if (flag == PEER_FLAG_SHUTDOWN)
+    {
+      if (CHECK_FLAG (peer->flags, flag))
+	{
+	  if (peer->status == Established)
+	    bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+			     BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
+	  else
+	    BGP_EVENT_ADD (peer, BGP_Stop);
+	}
+      else
+	{
+	  peer->v_start = BGP_INIT_START_TIMER;
+	  BGP_EVENT_ADD (peer, BGP_Stop);
+	}
+    }
+  else if (peer->status == Established)
+    {
+      if (flag == PEER_FLAG_NO_ROUTE_REFRESH_CAP
+	  && CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
+	{
+	  if (CHECK_FLAG (peer->flags, flag))
+	    UNSET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
+	  else
+	    SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
+
+	  bgp_capability_send (peer, AFI_IP, SAFI_UNICAST,
+			       CAPABILITY_CODE_REFRESH,
+			       CHECK_FLAG (peer->flags, flag) ?
+			       CAPABILITY_ACTION_UNSET : CAPABILITY_ACTION_SET);
+	}
+      else
+	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+    }
+  else
+    BGP_EVENT_ADD (peer, BGP_Stop);
+}
+
+/* Change specified peer flag. */
+int
+peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
+{
+  int found;
+  int size;
+  struct peer_group *group;
+  struct listnode *nn;
+  struct peer_flag_action action;
+
+  memset (&action, 0, sizeof (struct peer_flag_action));
+  size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
+
+  found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
+
+  /* No flag action is found.  */
+  if (! found)
+    return BGP_ERR_INVALID_FLAG;    
+
+  /* Not for peer-group member.  */
+  if (action.not_for_member && peer_group_active (peer))
+    return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
+
+  /* When unset the peer-group member's flag we have to check
+     peer-group configuration.  */
+  if (! set && peer_group_active (peer))
+    if (CHECK_FLAG (peer->group->conf->flags, flag))
+      {
+	if (flag == PEER_FLAG_SHUTDOWN)
+	  return BGP_ERR_PEER_GROUP_SHUTDOWN;
+	else
+	  return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
+      }
+
+  /* Flag conflict check.  */
+  if (set
+      && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
+      && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
+    return BGP_ERR_PEER_FLAG_CONFLICT;
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    {
+      if (set && CHECK_FLAG (peer->flags, flag) == flag)
+	return 0;
+      if (! set && ! CHECK_FLAG (peer->flags, flag))
+	return 0;
+    }
+
+  if (set)
+    SET_FLAG (peer->flags, flag);
+  else
+    UNSET_FLAG (peer->flags, flag);
+ 
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    {
+      if (action.type == peer_change_reset)
+	peer_flag_modify_action (peer, flag);
+
+      return 0;
+    }
+
+  /* peer-group member updates. */
+  group = peer->group;
+
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      if (set && CHECK_FLAG (peer->flags, flag) == flag)
+	continue;
+
+      if (! set && ! CHECK_FLAG (peer->flags, flag))
+	continue;
+
+      if (set)
+	SET_FLAG (peer->flags, flag);
+      else
+	UNSET_FLAG (peer->flags, flag);
+
+      if (action.type == peer_change_reset)
+	peer_flag_modify_action (peer, flag);
+    }
+  return 0;
+}
+
+int
+peer_flag_set (struct peer *peer, u_int32_t flag)
+{
+  return peer_flag_modify (peer, flag, 1);
+}
+
+int
+peer_flag_unset (struct peer *peer, u_int32_t flag)
+{
+  return peer_flag_modify (peer, flag, 0);
+}
+
+int
+peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
+{
+  if (peer->af_group[afi][safi])
+    return 1;
+  return 0;
+}
+
+int
+peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
+		     int set)
+{
+  int found;
+  int size;
+  struct listnode *nn;
+  struct peer_group *group;
+  struct peer_flag_action action;
+
+  memset (&action, 0, sizeof (struct peer_flag_action));
+  size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
+  
+  found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
+  
+  /* No flag action is found.  */
+  if (! found)
+    return BGP_ERR_INVALID_FLAG;    
+
+  /* Adress family must be activated.  */
+  if (! peer->afc[afi][safi])
+    return BGP_ERR_PEER_INACTIVE;
+
+  /* Not for peer-group member.  */
+  if (action.not_for_member && peer_is_group_member (peer, afi, safi))
+    return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
+
+ /* Spcecial check for reflector client.  */
+  if (flag & PEER_FLAG_REFLECTOR_CLIENT
+      && peer_sort (peer) != BGP_PEER_IBGP)
+    return BGP_ERR_NOT_INTERNAL_PEER;
+
+  /* Spcecial check for remove-private-AS.  */
+  if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
+      && peer_sort (peer) == BGP_PEER_IBGP)
+    return BGP_ERR_REMOVE_PRIVATE_AS;
+
+  /* When unset the peer-group member's flag we have to check
+     peer-group configuration.  */
+  if (! set && peer->af_group[afi][safi])
+    if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
+      return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
+
+  /* When current flag configuration is same as requested one.  */
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    {
+      if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
+	return 0;
+      if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
+	return 0;
+    }
+
+  if (set)
+    SET_FLAG (peer->af_flags[afi][safi], flag);
+  else
+    UNSET_FLAG (peer->af_flags[afi][safi], flag);
+
+  /* Execute action when peer is established.  */
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
+      && peer->status == Established)
+    {
+      if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
+	bgp_clear_adj_in (peer, afi, safi);
+      else
+	peer_change_action (peer, afi, safi, action.type);
+    }
+
+  /* Peer group member updates.  */
+  if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    {
+      group = peer->group;
+      
+      LIST_LOOP (group->peer, peer, nn)
+	{
+	  if (! peer->af_group[afi][safi])
+	    continue;
+
+	  if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
+	    continue;
+
+	  if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
+	    continue;
+
+	  if (set)
+	    SET_FLAG (peer->af_flags[afi][safi], flag);
+	  else
+	    UNSET_FLAG (peer->af_flags[afi][safi], flag);
+
+	  if (peer->status == Established)
+	    {
+	      if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
+		bgp_clear_adj_in (peer, afi, safi);
+	      else
+		peer_change_action (peer, afi, safi, action.type);
+	    }
+	}
+    }
+  return 0;
+}
+
+int
+peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
+{
+  return peer_af_flag_modify (peer, afi, safi, flag, 1);
+}
+
+int
+peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
+{
+  return peer_af_flag_modify (peer, afi, safi, flag, 0);
+}
+
+/* EBGP multihop configuration. */
+int
+peer_ebgp_multihop_set (struct peer *peer, int ttl)
+{
+  struct peer_group *group;
+  struct listnode *nn;
+
+  if (peer_sort (peer) == BGP_PEER_IBGP)
+    return 0;
+
+  peer->ttl = ttl;
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    {
+      if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
+	sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
+    }
+  else
+    {
+      group = peer->group;
+      LIST_LOOP (group->peer, peer, nn)
+	{
+	  if (peer_sort (peer) == BGP_PEER_IBGP)
+	    continue;
+
+	  peer->ttl = group->conf->ttl;
+
+	  if (peer->fd >= 0)
+	    sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
+	}
+    }
+  return 0;
+}
+
+int
+peer_ebgp_multihop_unset (struct peer *peer)
+{
+  struct peer_group *group;
+  struct listnode *nn;
+
+  if (peer_sort (peer) == BGP_PEER_IBGP)
+    return 0;
+
+  if (peer_group_active (peer))
+    peer->ttl = peer->group->conf->ttl;
+  else
+    peer->ttl = 1;
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    {
+      if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
+	sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
+    }
+  else
+    {
+      group = peer->group;
+      LIST_LOOP (group->peer, peer, nn)
+	{
+	  if (peer_sort (peer) == BGP_PEER_IBGP)
+	    continue;
+
+	  peer->ttl = 1;
+	  
+	  if (peer->fd >= 0)
+	    sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
+	}
+    }
+  return 0;
+}
+
+/* Neighbor description. */
+int
+peer_description_set (struct peer *peer, char *desc)
+{
+  if (peer->desc)
+    XFREE (MTYPE_PEER_DESC, peer->desc);
+
+  peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
+
+  return 0;
+}
+
+int
+peer_description_unset (struct peer *peer)
+{
+  if (peer->desc)
+    XFREE (MTYPE_PEER_DESC, peer->desc);
+
+  peer->desc = NULL;
+
+  return 0;
+}
+
+/* Neighbor update-source. */
+int
+peer_update_source_if_set (struct peer *peer, char *ifname)
+{
+  struct peer_group *group;
+  struct listnode *nn;
+
+  if (peer->update_if)
+    {
+      if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
+	  && strcmp (peer->update_if, ifname) == 0)
+	return 0;
+
+      XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
+      peer->update_if = NULL;
+    }
+
+  if (peer->update_source)
+    {
+      sockunion_free (peer->update_source);
+      peer->update_source = NULL;
+    }
+
+  peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    {
+      if (peer->status == Established)
+	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+      else
+	BGP_EVENT_ADD (peer, BGP_Stop);
+      return 0;
+    }
+
+  /* peer-group member updates. */
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      if (peer->update_if)
+	{
+	  if (strcmp (peer->update_if, ifname) == 0)
+	    continue;
+
+	  XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
+	  peer->update_if = NULL;
+	}
+
+      if (peer->update_source)
+	{
+	  sockunion_free (peer->update_source);
+	  peer->update_source = NULL;
+	}
+
+      peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
+
+      if (peer->status == Established)
+	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+      else
+	BGP_EVENT_ADD (peer, BGP_Stop);
+    }
+  return 0;
+}
+
+int
+peer_update_source_addr_set (struct peer *peer, union sockunion *su)
+{
+  struct peer_group *group;
+  struct listnode *nn;
+
+  if (peer->update_source)
+    {
+      if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
+	  && sockunion_cmp (peer->update_source, su) == 0)
+	return 0;
+      sockunion_free (peer->update_source);
+      peer->update_source = NULL;
+    }
+
+  if (peer->update_if)
+    {
+      XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
+      peer->update_if = NULL;
+    }
+
+  peer->update_source = sockunion_dup (su);
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    {
+      if (peer->status == Established)
+	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+      else
+	BGP_EVENT_ADD (peer, BGP_Stop);
+      return 0;
+    }
+
+  /* peer-group member updates. */
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      if (peer->update_source)
+	{
+	  if (sockunion_cmp (peer->update_source, su) == 0)
+	    continue;
+	  sockunion_free (peer->update_source);
+	  peer->update_source = NULL;
+	}
+
+      if (peer->update_if)
+	{
+	  XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
+	  peer->update_if = NULL;
+	}
+
+      peer->update_source = sockunion_dup (su);
+
+      if (peer->status == Established)
+	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+      else
+	BGP_EVENT_ADD (peer, BGP_Stop);
+    }
+  return 0;
+}
+
+int
+peer_update_source_unset (struct peer *peer)
+{
+  union sockunion *su;
+  struct peer_group *group;
+  struct listnode *nn;
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
+      && ! peer->update_source
+      && ! peer->update_if)
+    return 0;
+
+  if (peer->update_source)
+    {
+      sockunion_free (peer->update_source);
+      peer->update_source = NULL;
+    }
+  if (peer->update_if)
+    {
+      XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
+      peer->update_if = NULL;
+    }
+
+  if (peer_group_active (peer))
+    {
+      group = peer->group;
+
+      if (group->conf->update_source)
+	{
+	  su = sockunion_dup (group->conf->update_source);
+	  peer->update_source = su;
+	}
+      else if (group->conf->update_if)
+	peer->update_if = 
+	  XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
+    }
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    {
+      if (peer->status == Established)
+	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+      else
+	BGP_EVENT_ADD (peer, BGP_Stop);
+      return 0;
+    }
+
+  /* peer-group member updates. */
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      if (! peer->update_source && ! peer->update_if)
+	continue;
+
+      if (peer->update_source)
+	{
+	  sockunion_free (peer->update_source);
+	  peer->update_source = NULL;
+	}
+
+      if (peer->update_if)
+	{
+	  XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
+	  peer->update_if = NULL;
+	}
+
+      if (peer->status == Established)
+	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+			 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+      else
+	BGP_EVENT_ADD (peer, BGP_Stop);
+    }
+  return 0;
+}
+
+int
+peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
+			    char *rmap)
+{
+  struct peer_group *group;
+  struct listnode *nn;
+
+  /* Adress family must be activated.  */
+  if (! peer->afc[afi][safi])
+    return BGP_ERR_PEER_INACTIVE;
+
+  /* Default originate can't be used for peer group memeber.  */
+  if (peer_is_group_member (peer, afi, safi))
+    return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
+
+  if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
+      || (rmap && ! peer->default_rmap[afi][safi].name)
+      || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
+    { 
+      SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
+
+      if (rmap)
+	{
+	  if (peer->default_rmap[afi][safi].name)
+	    free (peer->default_rmap[afi][safi].name);
+	  peer->default_rmap[afi][safi].name = strdup (rmap);
+	  peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
+	}
+    }
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    {
+      if (peer->status == Established && peer->afc_nego[afi][safi])
+	bgp_default_originate (peer, afi, safi, 0);
+      return 0;
+    }
+
+  /* peer-group member updates. */
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
+
+      if (rmap)
+	{
+	  if (peer->default_rmap[afi][safi].name)
+	    free (peer->default_rmap[afi][safi].name);
+	  peer->default_rmap[afi][safi].name = strdup (rmap);
+	  peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
+	}
+
+      if (peer->status == Established && peer->afc_nego[afi][safi])
+	bgp_default_originate (peer, afi, safi, 0);
+    }
+  return 0;
+}
+
+int
+peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
+{
+  struct peer_group *group;
+  struct listnode *nn;
+
+  /* Adress family must be activated.  */
+  if (! peer->afc[afi][safi])
+    return BGP_ERR_PEER_INACTIVE;
+
+  /* Default originate can't be used for peer group memeber.  */
+  if (peer_is_group_member (peer, afi, safi))
+    return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
+
+  if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
+    { 
+      UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
+
+      if (peer->default_rmap[afi][safi].name)
+	free (peer->default_rmap[afi][safi].name);
+      peer->default_rmap[afi][safi].name = NULL;
+      peer->default_rmap[afi][safi].map = NULL;
+    }
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    {
+      if (peer->status == Established && peer->afc_nego[afi][safi])
+	bgp_default_originate (peer, afi, safi, 1);
+      return 0;
+    }
+
+  /* peer-group member updates. */
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
+
+      if (peer->default_rmap[afi][safi].name)
+	free (peer->default_rmap[afi][safi].name);
+      peer->default_rmap[afi][safi].name = NULL;
+      peer->default_rmap[afi][safi].map = NULL;
+
+      if (peer->status == Established && peer->afc_nego[afi][safi])
+	bgp_default_originate (peer, afi, safi, 1);
+    }
+  return 0;
+}
+
+int
+peer_port_set (struct peer *peer, u_int16_t port)
+{
+  peer->port = port;
+  return 0;
+}
+
+int
+peer_port_unset (struct peer *peer)
+{
+  peer->port = BGP_PORT_DEFAULT;
+  return 0;
+}
+
+/* neighbor weight. */
+int
+peer_weight_set (struct peer *peer, u_int16_t weight)
+{
+  struct peer_group *group;
+  struct listnode *nn;
+
+  SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
+  peer->weight = weight;
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    return 0;
+
+  /* peer-group member updates. */
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      peer->weight = group->conf->weight;
+    }
+  return 0;
+}
+
+int
+peer_weight_unset (struct peer *peer)
+{
+  struct peer_group *group;
+  struct listnode *nn;
+
+  /* Set default weight. */
+  if (peer_group_active (peer))
+    peer->weight = peer->group->conf->weight;
+  else
+    peer->weight = 0;
+
+  UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    return 0;
+
+  /* peer-group member updates. */
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      peer->weight = 0;
+    }
+  return 0;
+}
+
+int
+peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
+{
+  struct peer_group *group;
+  struct listnode *nn;
+
+  /* Not for peer group memeber.  */
+  if (peer_group_active (peer))
+    return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
+
+  /* keepalive value check.  */
+  if (keepalive > 65535)
+    return BGP_ERR_INVALID_VALUE;
+
+  /* Holdtime value check.  */
+  if (holdtime > 65535)
+    return BGP_ERR_INVALID_VALUE;
+
+  /* Holdtime value must be either 0 or greater than 3.  */
+  if (holdtime < 3 && holdtime != 0)
+    return BGP_ERR_INVALID_VALUE;
+
+  /* Set value to the configuration. */
+  SET_FLAG (peer->config, PEER_CONFIG_TIMER);
+  peer->holdtime = holdtime;
+  peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    return 0;
+
+  /* peer-group member updates. */
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      SET_FLAG (peer->config, PEER_CONFIG_TIMER);
+      peer->holdtime = group->conf->holdtime;
+      peer->keepalive = group->conf->keepalive;
+    }
+  return 0;
+}
+
+int
+peer_timers_unset (struct peer *peer)
+{
+  struct peer_group *group;
+  struct listnode *nn;
+
+  if (peer_group_active (peer))
+    return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
+
+  /* Clear configuration. */
+  UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
+  peer->keepalive = 0;
+  peer->holdtime = 0;
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    return 0;
+
+  /* peer-group member updates. */
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
+      peer->holdtime = 0;
+      peer->keepalive = 0;
+    }
+
+  return 0;
+}
+
+int
+peer_timers_connect_set (struct peer *peer, u_int32_t connect)
+{
+  if (peer_group_active (peer))
+    return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
+
+  if (connect > 65535)
+    return BGP_ERR_INVALID_VALUE;
+
+  /* Set value to the configuration. */
+  SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
+  peer->connect = connect;
+
+  /* Set value to timer setting. */
+  peer->v_connect = connect;
+
+  return 0;
+}
+
+int
+peer_timers_connect_unset (struct peer *peer)
+{
+  if (peer_group_active (peer))
+    return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
+
+  /* Clear configuration. */
+  UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
+  peer->connect = 0;
+
+  /* Set timer setting to default value. */
+  peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
+
+  return 0;
+}
+
+int
+peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
+{
+  if (peer_group_active (peer))
+    return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
+
+  if (routeadv > 600)
+    return BGP_ERR_INVALID_VALUE;
+
+  SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
+  peer->routeadv = routeadv;
+  peer->v_routeadv = routeadv;
+
+  return 0;
+}
+
+int
+peer_advertise_interval_unset (struct peer *peer)
+{
+  if (peer_group_active (peer))
+    return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
+
+  UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
+  peer->routeadv = 0;
+
+  if (peer_sort (peer) == BGP_PEER_IBGP)
+    peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
+  else
+    peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
+  
+  return 0;
+}
+
+int
+peer_version_set (struct peer *peer, int version)
+{
+  if (version != BGP_VERSION_4 && version != BGP_VERSION_MP_4_DRAFT_00)
+    return BGP_ERR_INVALID_VALUE;
+
+  peer->version = version;
+
+  return 0;
+}
+
+int
+peer_version_unset (struct peer *peer)
+{
+  peer->version = BGP_VERSION_4;
+  return 0;
+}
+
+/* neighbor interface */
+int
+peer_interface_set (struct peer *peer, char *str)
+{
+  if (peer->ifname)
+    free (peer->ifname);
+  peer->ifname = strdup (str);
+
+  return 0;
+}
+
+int
+peer_interface_unset (struct peer *peer)
+{
+  if (peer->ifname)
+    free (peer->ifname);
+  peer->ifname = NULL;
+
+  return 0;
+}
+
+/* Allow-as in.  */
+int
+peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
+{
+  struct peer_group *group;
+  struct listnode *nn;
+
+  if (allow_num < 1 || allow_num > 10)
+    return BGP_ERR_INVALID_VALUE;
+
+  if (peer->allowas_in[afi][safi] != allow_num)
+    {
+      peer->allowas_in[afi][safi] = allow_num;
+      SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
+      peer_change_action (peer, afi, safi, peer_change_reset_in);
+    }
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    return 0;
+
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      if (peer->allowas_in[afi][safi] != allow_num)
+	{
+	  peer->allowas_in[afi][safi] = allow_num;
+	  SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
+	  peer_change_action (peer, afi, safi, peer_change_reset_in);
+	}
+	  
+    }
+  return 0;
+}
+
+int
+peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
+{
+  struct peer_group *group;
+  struct listnode *nn;
+
+  if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
+    {
+      peer->allowas_in[afi][safi] = 0;
+      peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
+    }
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    return 0;
+
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
+	{
+	  peer->allowas_in[afi][safi] = 0;
+	  peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
+	}
+    }
+  return 0;
+}
+
+int
+peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
+{
+  struct bgp *bgp = peer->bgp;
+  struct peer_group *group;
+  struct listnode *nn;
+
+  if (peer_sort (peer) != BGP_PEER_EBGP
+      && peer_sort (peer) != BGP_PEER_INTERNAL)
+    return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
+
+  if (bgp->as == as)
+    return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
+
+  if (peer_group_active (peer))
+    return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
+
+  if (peer->change_local_as == as &&
+      ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
+       || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
+    return 0;
+
+  peer->change_local_as = as;
+  if (no_prepend)
+    SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
+  else
+    UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    {
+      if (peer->status == Established)
+        bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+      else
+        BGP_EVENT_ADD (peer, BGP_Stop);
+
+      return 0;
+    }
+
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      peer->change_local_as = as;
+      if (no_prepend)
+	SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
+      else
+	UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
+
+      if (peer->status == Established)
+        bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+      else
+        BGP_EVENT_ADD (peer, BGP_Stop);
+    }
+
+  return 0;
+}
+
+int
+peer_local_as_unset (struct peer *peer)
+{
+  struct peer_group *group;
+  struct listnode *nn;
+
+  if (peer_group_active (peer))
+    return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
+
+  if (! peer->change_local_as)
+    return 0;
+
+  peer->change_local_as = 0;
+  UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    {
+      if (peer->status == Established)
+        bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+      else
+        BGP_EVENT_ADD (peer, BGP_Stop);
+
+      return 0;
+    }
+
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      peer->change_local_as = 0;
+      UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
+
+      if (peer->status == Established)
+        bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
+      else
+        BGP_EVENT_ADD (peer, BGP_Stop);
+    }
+  return 0;
+}
+
+/* Set distribute list to the peer. */
+int
+peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct, 
+		     char *name)
+{
+  struct bgp_filter *filter;
+  struct peer_group *group;
+  struct listnode *nn;
+
+  if (! peer->afc[afi][safi])
+    return BGP_ERR_PEER_INACTIVE;
+
+  if (direct != FILTER_IN && direct != FILTER_OUT)
+    return BGP_ERR_INVALID_VALUE;
+
+  if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
+    return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
+
+  filter = &peer->filter[afi][safi];
+
+  if (filter->plist[direct].name)
+    return BGP_ERR_PEER_FILTER_CONFLICT;
+
+  if (filter->dlist[direct].name)
+    free (filter->dlist[direct].name);
+  filter->dlist[direct].name = strdup (name);
+  filter->dlist[direct].alist = access_list_lookup (afi, name);
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    return 0;
+
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      filter = &peer->filter[afi][safi];
+
+      if (! peer->af_group[afi][safi])
+	continue;
+
+      if (filter->dlist[direct].name)
+	free (filter->dlist[direct].name);
+      filter->dlist[direct].name = strdup (name);
+      filter->dlist[direct].alist = access_list_lookup (afi, name);
+    }
+
+  return 0;
+}
+
+int
+peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
+{
+  struct bgp_filter *filter;
+  struct bgp_filter *gfilter;
+  struct peer_group *group;
+  struct listnode *nn;
+
+  if (! peer->afc[afi][safi])
+    return BGP_ERR_PEER_INACTIVE;
+
+  if (direct != FILTER_IN && direct != FILTER_OUT)
+    return BGP_ERR_INVALID_VALUE;
+
+  if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
+    return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
+
+  filter = &peer->filter[afi][safi];
+
+  /* apply peer-group filter */
+  if (peer->af_group[afi][safi])
+    {
+      gfilter = &peer->group->conf->filter[afi][safi];
+
+      if (gfilter->dlist[direct].name)
+	{
+	  if (filter->dlist[direct].name)
+	    free (filter->dlist[direct].name);
+	  filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
+	  filter->dlist[direct].alist = gfilter->dlist[direct].alist;
+	  return 0;
+	}
+    }
+
+  if (filter->dlist[direct].name)
+    free (filter->dlist[direct].name);
+  filter->dlist[direct].name = NULL;
+  filter->dlist[direct].alist = NULL;
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    return 0;
+
+    group = peer->group;
+    LIST_LOOP (group->peer, peer, nn)
+      {
+	filter = &peer->filter[afi][safi];
+
+	if (! peer->af_group[afi][safi])
+	  continue;
+
+	if (filter->dlist[direct].name)
+	  free (filter->dlist[direct].name);
+	filter->dlist[direct].name = NULL;
+	filter->dlist[direct].alist = NULL;
+      }
+
+  return 0;
+}
+
+/* Update distribute list. */
+void
+peer_distribute_update (struct access_list *access)
+{
+  afi_t afi;
+  safi_t safi;
+  int direct;
+  struct listnode *nn, *nm;
+  struct bgp *bgp;
+  struct peer *peer;
+  struct peer_group *group;
+  struct bgp_filter *filter;
+
+  LIST_LOOP (bm->bgp, bgp, nn)
+    {
+      LIST_LOOP (bgp->peer, peer, nm)
+	{
+	  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+	    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+	      {
+		filter = &peer->filter[afi][safi];
+
+		for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
+		  {
+		    if (filter->dlist[direct].name)
+		      filter->dlist[direct].alist = 
+			access_list_lookup (afi, filter->dlist[direct].name);
+		    else
+		      filter->dlist[direct].alist = NULL;
+		  }
+	      }
+	}
+      LIST_LOOP (bgp->group, group, nm)
+	{
+	  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+	    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+	      {
+		filter = &group->conf->filter[afi][safi];
+
+		for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
+		  {
+		    if (filter->dlist[direct].name)
+		      filter->dlist[direct].alist = 
+			access_list_lookup (afi, filter->dlist[direct].name);
+		    else
+		      filter->dlist[direct].alist = NULL;
+		  }
+	      }
+	}
+    }
+}
+
+/* Set prefix list to the peer. */
+int
+peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct, 
+		      char *name)
+{
+  struct bgp_filter *filter;
+  struct peer_group *group;
+  struct listnode *nn;
+
+  if (! peer->afc[afi][safi])
+    return BGP_ERR_PEER_INACTIVE;
+
+  if (direct != FILTER_IN && direct != FILTER_OUT)
+    return BGP_ERR_INVALID_VALUE;
+
+  if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
+    return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
+
+  filter = &peer->filter[afi][safi];
+
+  if (filter->dlist[direct].name)
+    return BGP_ERR_PEER_FILTER_CONFLICT;
+
+  if (filter->plist[direct].name)
+    free (filter->plist[direct].name);
+  filter->plist[direct].name = strdup (name);
+  filter->plist[direct].plist = prefix_list_lookup (afi, name);
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    return 0;
+
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      filter = &peer->filter[afi][safi];
+
+      if (! peer->af_group[afi][safi])
+	continue;
+
+      if (filter->plist[direct].name)
+	free (filter->plist[direct].name);
+      filter->plist[direct].name = strdup (name);
+      filter->plist[direct].plist = prefix_list_lookup (afi, name);
+    }
+  return 0;
+}
+
+int
+peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
+{
+  struct bgp_filter *filter;
+  struct bgp_filter *gfilter;
+  struct peer_group *group;
+  struct listnode *nn;
+
+  if (! peer->afc[afi][safi])
+    return BGP_ERR_PEER_INACTIVE;
+
+  if (direct != FILTER_IN && direct != FILTER_OUT)
+    return BGP_ERR_INVALID_VALUE;
+
+  if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
+    return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
+
+  filter = &peer->filter[afi][safi];
+
+  /* apply peer-group filter */
+  if (peer->af_group[afi][safi])
+    {
+      gfilter = &peer->group->conf->filter[afi][safi];
+
+      if (gfilter->plist[direct].name)
+	{
+	  if (filter->plist[direct].name)
+	    free (filter->plist[direct].name);
+	  filter->plist[direct].name = strdup (gfilter->plist[direct].name);
+	  filter->plist[direct].plist = gfilter->plist[direct].plist;
+	  return 0;
+	}
+    }
+
+  if (filter->plist[direct].name)
+    free (filter->plist[direct].name);
+  filter->plist[direct].name = NULL;
+  filter->plist[direct].plist = NULL;
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    return 0;
+
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      filter = &peer->filter[afi][safi];
+
+      if (! peer->af_group[afi][safi])
+	continue;
+
+      if (filter->plist[direct].name)
+	free (filter->plist[direct].name);
+      filter->plist[direct].name = NULL;
+      filter->plist[direct].plist = NULL;
+    }
+
+  return 0;
+}
+
+/* Update prefix-list list. */
+void
+peer_prefix_list_update (struct prefix_list *plist)
+{
+  struct listnode *nn, *nm;
+  struct bgp *bgp;
+  struct peer *peer;
+  struct peer_group *group;
+  struct bgp_filter *filter;
+  afi_t afi;
+  safi_t safi;
+  int direct;
+
+  LIST_LOOP (bm->bgp, bgp, nn)
+    {
+      LIST_LOOP (bgp->peer, peer, nm)
+	{
+	  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+	    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+	      {
+		filter = &peer->filter[afi][safi];
+
+		for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
+		  {
+		    if (filter->plist[direct].name)
+		      filter->plist[direct].plist = 
+			prefix_list_lookup (afi, filter->plist[direct].name);
+		    else
+		      filter->plist[direct].plist = NULL;
+		  }
+	      }
+	}
+      LIST_LOOP (bgp->group, group, nm)
+	{
+	  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+	    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+	      {
+		filter = &group->conf->filter[afi][safi];
+
+		for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
+		  {
+		    if (filter->plist[direct].name)
+		      filter->plist[direct].plist = 
+			prefix_list_lookup (afi, filter->plist[direct].name);
+		    else
+		      filter->plist[direct].plist = NULL;
+		  }
+	      }
+	}
+    }
+}
+
+int
+peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
+		 char *name)
+{
+  struct bgp_filter *filter;
+  struct peer_group *group;
+  struct listnode *nn;
+
+  if (! peer->afc[afi][safi])
+    return BGP_ERR_PEER_INACTIVE;
+
+  if (direct != FILTER_IN && direct != FILTER_OUT)
+    return BGP_ERR_INVALID_VALUE;
+
+  if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
+    return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
+
+  filter = &peer->filter[afi][safi];
+
+  if (filter->aslist[direct].name)
+    free (filter->aslist[direct].name);
+  filter->aslist[direct].name = strdup (name);
+  filter->aslist[direct].aslist = as_list_lookup (name);
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    return 0;
+
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      filter = &peer->filter[afi][safi];
+
+      if (! peer->af_group[afi][safi])
+	continue;
+
+      if (filter->aslist[direct].name)
+	free (filter->aslist[direct].name);
+      filter->aslist[direct].name = strdup (name);
+      filter->aslist[direct].aslist = as_list_lookup (name);
+    }
+  return 0;
+}
+
+int
+peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
+{
+  struct bgp_filter *filter;
+  struct bgp_filter *gfilter;
+  struct peer_group *group;
+  struct listnode *nn;
+
+  if (! peer->afc[afi][safi])
+    return BGP_ERR_PEER_INACTIVE;
+
+  if (direct != FILTER_IN && direct != FILTER_OUT)
+    return BGP_ERR_INVALID_VALUE;
+
+  if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
+    return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
+
+  filter = &peer->filter[afi][safi];
+
+  /* apply peer-group filter */
+  if (peer->af_group[afi][safi])
+    {
+      gfilter = &peer->group->conf->filter[afi][safi];
+
+      if (gfilter->aslist[direct].name)
+	{
+	  if (filter->aslist[direct].name)
+	    free (filter->aslist[direct].name);
+	  filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
+	  filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
+	  return 0;
+	}
+    }
+
+  if (filter->aslist[direct].name)
+    free (filter->aslist[direct].name);
+  filter->aslist[direct].name = NULL;
+  filter->aslist[direct].aslist = NULL;
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    return 0;
+
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      filter = &peer->filter[afi][safi];
+
+      if (! peer->af_group[afi][safi])
+	continue;
+
+      if (filter->aslist[direct].name)
+	free (filter->aslist[direct].name);
+      filter->aslist[direct].name = NULL;
+      filter->aslist[direct].aslist = NULL;
+    }
+
+  return 0;
+}
+
+void
+peer_aslist_update ()
+{
+  afi_t afi;
+  safi_t safi;
+  int direct;
+  struct listnode *nn, *nm;
+  struct bgp *bgp;
+  struct peer *peer;
+  struct peer_group *group;
+  struct bgp_filter *filter;
+
+  LIST_LOOP (bm->bgp, bgp, nn)
+    {
+      LIST_LOOP (bgp->peer, peer, nm)
+	{
+	  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+	    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+	      {
+		filter = &peer->filter[afi][safi];
+
+		for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
+		  {
+		    if (filter->aslist[direct].name)
+		      filter->aslist[direct].aslist = 
+			as_list_lookup (filter->aslist[direct].name);
+		    else
+		      filter->aslist[direct].aslist = NULL;
+		  }
+	      }
+	}
+      LIST_LOOP (bgp->group, group, nm)
+	{
+	  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+	    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+	      {
+		filter = &group->conf->filter[afi][safi];
+
+		for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
+		  {
+		    if (filter->aslist[direct].name)
+		      filter->aslist[direct].aslist = 
+			as_list_lookup (filter->aslist[direct].name);
+		    else
+		      filter->aslist[direct].aslist = NULL;
+		  }
+	      }
+	}
+    }
+}
+
+/* Set route-map to the peer. */
+int
+peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct, 
+		    char *name)
+{
+  struct bgp_filter *filter;
+  struct peer_group *group;
+  struct listnode *nn;
+
+  if (! peer->afc[afi][safi])
+    return BGP_ERR_PEER_INACTIVE;
+
+  if (direct != FILTER_IN && direct != FILTER_OUT)
+    return BGP_ERR_INVALID_VALUE;
+
+  if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
+    return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
+
+  filter = &peer->filter[afi][safi];
+
+  if (filter->map[direct].name)
+    free (filter->map[direct].name);
+  
+  filter->map[direct].name = strdup (name);
+  filter->map[direct].map = route_map_lookup_by_name (name);
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    return 0;
+
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      filter = &peer->filter[afi][safi];
+
+      if (! peer->af_group[afi][safi])
+	continue;
+
+      if (filter->map[direct].name)
+	free (filter->map[direct].name);
+      filter->map[direct].name = strdup (name);
+      filter->map[direct].map = route_map_lookup_by_name (name);
+    }
+  return 0;
+}
+
+/* Unset route-map from the peer. */
+int
+peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
+{
+  struct bgp_filter *filter;
+  struct bgp_filter *gfilter;
+  struct peer_group *group;
+  struct listnode *nn;
+
+  if (! peer->afc[afi][safi])
+    return BGP_ERR_PEER_INACTIVE;
+
+  if (direct != FILTER_IN && direct != FILTER_OUT)
+    return BGP_ERR_INVALID_VALUE;
+
+  if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
+    return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
+
+  filter = &peer->filter[afi][safi];
+
+  /* apply peer-group filter */
+  if (peer->af_group[afi][safi])
+    {
+      gfilter = &peer->group->conf->filter[afi][safi];
+
+      if (gfilter->map[direct].name)
+	{
+	  if (filter->map[direct].name)
+	    free (filter->map[direct].name);
+	  filter->map[direct].name = strdup (gfilter->map[direct].name);
+	  filter->map[direct].map = gfilter->map[direct].map;
+	  return 0;
+	}
+    }
+
+  if (filter->map[direct].name)
+    free (filter->map[direct].name);
+  filter->map[direct].name = NULL;
+  filter->map[direct].map = NULL;
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    return 0;
+
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      filter = &peer->filter[afi][safi];
+
+      if (! peer->af_group[afi][safi])
+	continue;
+
+      if (filter->map[direct].name)
+	free (filter->map[direct].name);
+      filter->map[direct].name = NULL;
+      filter->map[direct].map = NULL;
+    }
+  return 0;
+}
+
+/* Set unsuppress-map to the peer. */
+int
+peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi, char *name)
+{
+  struct bgp_filter *filter;
+  struct peer_group *group;
+  struct listnode *nn;
+
+  if (! peer->afc[afi][safi])
+    return BGP_ERR_PEER_INACTIVE;
+
+  if (peer_is_group_member (peer, afi, safi))
+    return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
+      
+  filter = &peer->filter[afi][safi];
+
+  if (filter->usmap.name)
+    free (filter->usmap.name);
+  
+  filter->usmap.name = strdup (name);
+  filter->usmap.map = route_map_lookup_by_name (name);
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    return 0;
+
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      filter = &peer->filter[afi][safi];
+
+      if (! peer->af_group[afi][safi])
+	continue;
+
+      if (filter->usmap.name)
+	free (filter->usmap.name);
+      filter->usmap.name = strdup (name);
+      filter->usmap.map = route_map_lookup_by_name (name);
+    }
+  return 0;
+}
+
+/* Unset route-map from the peer. */
+int
+peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
+{
+  struct bgp_filter *filter;
+  struct peer_group *group;
+  struct listnode *nn;
+
+  if (! peer->afc[afi][safi])
+    return BGP_ERR_PEER_INACTIVE;
+  
+  if (peer_is_group_member (peer, afi, safi))
+    return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
+
+  filter = &peer->filter[afi][safi];
+
+  if (filter->usmap.name)
+    free (filter->usmap.name);
+  filter->usmap.name = NULL;
+  filter->usmap.map = NULL;
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    return 0;
+
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      filter = &peer->filter[afi][safi];
+
+      if (! peer->af_group[afi][safi])
+	continue;
+
+      if (filter->usmap.name)
+	free (filter->usmap.name);
+      filter->usmap.name = NULL;
+      filter->usmap.map = NULL;
+    }
+  return 0;
+}
+
+int
+peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
+			 u_int32_t max, int warning)
+{
+  struct peer_group *group;
+  struct listnode *nn;
+
+  if (! peer->afc[afi][safi])
+    return BGP_ERR_PEER_INACTIVE;
+
+  SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
+  peer->pmax[afi][safi] = max;
+  if (warning)
+    SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
+  else
+    UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    return 0;
+
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      if (! peer->af_group[afi][safi])
+	continue;
+
+      SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
+      peer->pmax[afi][safi] = max;
+      if (warning)
+	SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
+      else
+	UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
+    }
+  return 0;
+}
+
+int
+peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
+{
+  struct peer_group *group;
+  struct listnode *nn;
+
+  if (! peer->afc[afi][safi])
+    return BGP_ERR_PEER_INACTIVE;
+
+  /* apply peer-group config */
+  if (peer->af_group[afi][safi])
+    {
+      if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
+	  PEER_FLAG_MAX_PREFIX))
+	SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
+      else
+	UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
+
+      if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
+	  PEER_FLAG_MAX_PREFIX_WARNING))
+	SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
+      else
+	UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
+
+      peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
+      return 0;
+    }
+
+  UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
+  UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
+  peer->pmax[afi][safi] = 0;
+
+  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    return 0;
+
+  group = peer->group;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      if (! peer->af_group[afi][safi])
+	continue;
+
+      UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
+      UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
+      peer->pmax[afi][safi] = 0;
+    }
+  return 0;
+}
+
+int
+peer_clear (struct peer *peer)
+{
+  if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
+    {
+      UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
+      peer->v_start = BGP_INIT_START_TIMER;
+      if (peer->status == Established)
+	bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+			 BGP_NOTIFY_CEASE_ADMIN_RESET);
+      else
+        BGP_EVENT_ADD (peer, BGP_Stop);
+    }
+  return 0;
+}
+
+int
+peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
+		 enum bgp_clear_type stype)
+{
+  if (peer->status != Established)
+    return 0;
+
+  if (! peer->afc[afi][safi])
+    return BGP_ERR_AF_UNCONFIGURED;
+
+  if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
+    bgp_announce_route (peer, afi, safi);
+
+  if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
+    {
+      if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
+	  && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
+	      || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
+	{
+	  struct bgp_filter *filter = &peer->filter[afi][safi];
+	  u_char prefix_type;
+
+	  if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
+	    prefix_type = ORF_TYPE_PREFIX;
+	  else
+	    prefix_type = ORF_TYPE_PREFIX_OLD;
+
+	  if (filter->plist[FILTER_IN].plist)
+	    {
+	      if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
+		bgp_route_refresh_send (peer, afi, safi,
+					prefix_type, REFRESH_DEFER, 1);
+	      bgp_route_refresh_send (peer, afi, safi, prefix_type,
+				      REFRESH_IMMEDIATE, 0);
+	    }
+	  else
+	    {
+	      if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
+		bgp_route_refresh_send (peer, afi, safi,
+					prefix_type, REFRESH_IMMEDIATE, 1);
+	      else
+		bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
+	    }
+	  return 0;
+	}
+    }
+
+  if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
+      || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
+    {
+      /* If neighbor has soft reconfiguration inbound flag.
+	 Use Adj-RIB-In database. */
+      if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
+	bgp_soft_reconfig_in (peer, afi, safi);
+      else
+	{
+	  /* If neighbor has route refresh capability, send route refresh
+	     message to the peer. */
+	  if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
+	      || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
+	    bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
+	  else
+	    return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
+	}
+    }
+  return 0;
+}
+
+/* Display peer uptime. */
+char *
+peer_uptime (time_t uptime2, char *buf, size_t len)
+{
+  time_t uptime1;
+  struct tm *tm;
+
+  /* Check buffer length. */
+  if (len < BGP_UPTIME_LEN)
+    {
+      zlog_warn ("peer_uptime (): buffer shortage %d", len);
+      return "";
+    }
+
+  /* If there is no connection has been done before print `never'. */
+  if (uptime2 == 0)
+    {
+      snprintf (buf, len, "never   ");
+      return buf;
+    }
+
+  /* Get current time. */
+  uptime1 = time (NULL);
+  uptime1 -= uptime2;
+  tm = gmtime (&uptime1);
+
+  /* Making formatted timer strings. */
+#define ONE_DAY_SECOND 60*60*24
+#define ONE_WEEK_SECOND 60*60*24*7
+
+  if (uptime1 < ONE_DAY_SECOND)
+    snprintf (buf, len, "%02d:%02d:%02d", 
+	      tm->tm_hour, tm->tm_min, tm->tm_sec);
+  else if (uptime1 < ONE_WEEK_SECOND)
+    snprintf (buf, len, "%dd%02dh%02dm", 
+	      tm->tm_yday, tm->tm_hour, tm->tm_min);
+  else
+    snprintf (buf, len, "%02dw%dd%02dh", 
+	      tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
+  return buf;
+}
+
+void
+bgp_config_write_filter (struct vty *vty, struct peer *peer,
+			 afi_t afi, safi_t safi)
+{
+  struct bgp_filter *filter;
+  struct bgp_filter *gfilter = NULL;
+  char *addr;
+  int in = FILTER_IN;
+  int out = FILTER_OUT;
+
+  addr = peer->host;
+  filter = &peer->filter[afi][safi];
+  if (peer->af_group[afi][safi])
+    gfilter = &peer->group->conf->filter[afi][safi];
+
+  /* distribute-list. */
+  if (filter->dlist[in].name)
+    if (! gfilter || ! gfilter->dlist[in].name
+	|| strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
+    vty_out (vty, " neighbor %s distribute-list %s in%s", addr, 
+	     filter->dlist[in].name, VTY_NEWLINE);
+  if (filter->dlist[out].name && ! gfilter)
+    vty_out (vty, " neighbor %s distribute-list %s out%s", addr, 
+	     filter->dlist[out].name, VTY_NEWLINE);
+
+  /* prefix-list. */
+  if (filter->plist[in].name)
+    if (! gfilter || ! gfilter->plist[in].name
+	|| strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
+    vty_out (vty, " neighbor %s prefix-list %s in%s", addr, 
+	     filter->plist[in].name, VTY_NEWLINE);
+  if (filter->plist[out].name && ! gfilter)
+    vty_out (vty, " neighbor %s prefix-list %s out%s", addr, 
+	     filter->plist[out].name, VTY_NEWLINE);
+
+  /* route-map. */
+  if (filter->map[in].name)
+    if (! gfilter || ! gfilter->map[in].name
+	|| strcmp (filter->map[in].name, gfilter->map[in].name) != 0)
+      vty_out (vty, " neighbor %s route-map %s in%s", addr, 
+	       filter->map[in].name, VTY_NEWLINE);
+  if (filter->map[out].name && ! gfilter)
+    vty_out (vty, " neighbor %s route-map %s out%s", addr, 
+	     filter->map[out].name, VTY_NEWLINE);
+
+  /* unsuppress-map */
+  if (filter->usmap.name && ! gfilter)
+    vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
+	     filter->usmap.name, VTY_NEWLINE);
+
+  /* filter-list. */
+  if (filter->aslist[in].name)
+    if (! gfilter || ! gfilter->aslist[in].name
+	|| strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
+      vty_out (vty, " neighbor %s filter-list %s in%s", addr, 
+	       filter->aslist[in].name, VTY_NEWLINE);
+  if (filter->aslist[out].name && ! gfilter)
+    vty_out (vty, " neighbor %s filter-list %s out%s", addr, 
+	     filter->aslist[out].name, VTY_NEWLINE);
+}
+
+/* BGP peer configuration display function. */
+void
+bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
+		       struct peer *peer, afi_t afi, safi_t safi)
+{
+  struct bgp_filter *filter;
+  struct peer *g_peer = NULL;
+  char buf[SU_ADDRSTRLEN];
+  char *addr;
+
+  filter = &peer->filter[afi][safi];
+  addr = peer->host;
+  if (peer_group_active (peer))
+    g_peer = peer->group->conf;
+
+  /************************************
+   ****** Global to the neighbor ******
+   ************************************/
+  if (afi == AFI_IP && safi == SAFI_UNICAST)
+    {
+      /* remote-as. */
+      if (! peer_group_active (peer))
+	{
+	  if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+	    vty_out (vty, " neighbor %s peer-group%s", addr,
+		     VTY_NEWLINE);
+	  if (peer->as)
+	    vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
+		     VTY_NEWLINE);
+	}
+      else
+	{
+	  if (! g_peer->as)
+	    vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
+		     VTY_NEWLINE);
+	  if (peer->af_group[AFI_IP][SAFI_UNICAST])
+	    vty_out (vty, " neighbor %s peer-group %s%s", addr,
+		     peer->group->name, VTY_NEWLINE);
+	}
+
+      /* local-as. */
+      if (peer->change_local_as)
+	if (! peer_group_active (peer))
+	  vty_out (vty, " neighbor %s local-as %d%s%s", addr,
+		   peer->change_local_as,
+		   CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
+		   " no-prepend" : "", VTY_NEWLINE);
+
+      /* Description. */
+      if (peer->desc)
+	vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
+		 VTY_NEWLINE);
+
+      /* Shutdown. */
+      if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
+        if (! peer_group_active (peer) ||
+	    ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
+	  vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
+
+      /* BGP port. */
+      if (peer->port != BGP_PORT_DEFAULT)
+	vty_out (vty, " neighbor %s port %d%s", addr, peer->port, 
+		 VTY_NEWLINE);
+
+      /* Local interface name. */
+      if (peer->ifname)
+	vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
+		 VTY_NEWLINE);
+  
+      /* Passive. */
+      if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
+        if (! peer_group_active (peer) ||
+	    ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
+	  vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
+
+      /* EBGP multihop.  */
+      if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
+        if (! peer_group_active (peer) ||
+	    g_peer->ttl != peer->ttl)
+	  vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
+		   VTY_NEWLINE);
+
+      /* Enforce multihop.  */
+      if (CHECK_FLAG (peer->flags, PEER_FLAG_ENFORCE_MULTIHOP))
+	if (! peer_group_active (peer) ||
+	    ! CHECK_FLAG (g_peer->flags, PEER_FLAG_ENFORCE_MULTIHOP))
+	  vty_out (vty, " neighbor %s enforce-multihop%s", addr, VTY_NEWLINE);
+
+      /* Update-source. */
+      if (peer->update_if)
+	if (! peer_group_active (peer) || ! g_peer->update_if
+	    || strcmp (g_peer->update_if, peer->update_if) != 0)
+	  vty_out (vty, " neighbor %s update-source %s%s", addr,
+		   peer->update_if, VTY_NEWLINE);
+      if (peer->update_source)
+	if (! peer_group_active (peer) || ! g_peer->update_source
+	    || sockunion_cmp (g_peer->update_source,
+			      peer->update_source) != 0)
+	  vty_out (vty, " neighbor %s update-source %s%s", addr,
+		   sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
+		   VTY_NEWLINE);
+
+      /* BGP version print. */
+      if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
+	vty_out (vty, " neighbor %s version %s%s",
+		 addr,"4-", VTY_NEWLINE);
+
+      /* advertisement-interval */
+      if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
+	vty_out (vty, " neighbor %s advertisement-interval %d%s",
+		 addr, peer->v_routeadv, VTY_NEWLINE); 
+
+      /* timers. */
+      if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
+	  && ! peer_group_active (peer))
+	  vty_out (vty, " neighbor %s timers %d %d%s", addr, 
+	  peer->keepalive, peer->holdtime, VTY_NEWLINE);
+
+      if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
+	  vty_out (vty, " neighbor %s timers connect %d%s", addr, 
+	  peer->connect, VTY_NEWLINE);
+
+      /* Default weight. */
+      if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
+        if (! peer_group_active (peer) ||
+	    g_peer->weight != peer->weight)
+	  vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
+		   VTY_NEWLINE);
+
+      /* Route refresh. */
+      if (CHECK_FLAG (peer->flags, PEER_FLAG_NO_ROUTE_REFRESH_CAP))
+        if (! peer_group_active (peer) ||
+	    ! CHECK_FLAG (g_peer->flags, PEER_FLAG_NO_ROUTE_REFRESH_CAP))
+	  vty_out (vty, " no neighbor %s capability route-refresh%s", addr,
+	  VTY_NEWLINE);
+
+      /* Dynamic capability.  */
+      if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
+        if (! peer_group_active (peer) ||
+	    ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
+	vty_out (vty, " neighbor %s capability dynamic%s", addr,
+	     VTY_NEWLINE);
+
+      /* dont capability negotiation. */
+      if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
+        if (! peer_group_active (peer) ||
+	    ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
+	vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
+		 VTY_NEWLINE);
+
+      /* override capability negotiation. */
+      if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
+        if (! peer_group_active (peer) ||
+	    ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
+	vty_out (vty, " neighbor %s override-capability%s", addr,
+		 VTY_NEWLINE);
+
+      /* strict capability negotiation. */
+      if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
+        if (! peer_group_active (peer) ||
+	    ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
+	vty_out (vty, " neighbor %s strict-capability-match%s", addr,
+	     VTY_NEWLINE);
+
+      if (! peer_group_active (peer))
+	{
+	  if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
+	    {
+	      if (peer->afc[AFI_IP][SAFI_UNICAST])
+		vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
+	    }
+          else
+	    {
+	      if (! peer->afc[AFI_IP][SAFI_UNICAST])
+		vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
+	    }
+	}
+    }
+
+
+  /************************************
+   ****** Per AF to the neighbor ******
+   ************************************/
+
+  if (! (afi == AFI_IP && safi == SAFI_UNICAST))
+    {
+      if (peer->af_group[afi][safi])
+	vty_out (vty, " neighbor %s peer-group %s%s", addr,
+		 peer->group->name, VTY_NEWLINE);
+      else
+	vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
+    }
+
+  /* ORF capability.  */
+  if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
+      || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
+    if (! peer->af_group[afi][safi])
+    {
+      vty_out (vty, " neighbor %s capability orf prefix-list", addr);
+
+      if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
+	  && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
+	vty_out (vty, " both");
+      else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
+	vty_out (vty, " send");
+      else
+	vty_out (vty, " receive");
+      vty_out (vty, "%s", VTY_NEWLINE);
+    }
+
+  /* Route reflector client. */
+  if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
+      && ! peer->af_group[afi][safi])
+    vty_out (vty, " neighbor %s route-reflector-client%s", addr, 
+	     VTY_NEWLINE);
+
+  /* Nexthop self. */
+  if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
+      && ! peer->af_group[afi][safi])
+    vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
+
+  /* Remove private AS. */
+  if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
+      && ! peer->af_group[afi][safi])
+    vty_out (vty, " neighbor %s remove-private-AS%s",
+	     addr, VTY_NEWLINE);
+
+  /* send-community print. */
+  if (! peer->af_group[afi][safi])
+    {
+      if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
+	{
+	  if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
+	      && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
+	    vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
+	  else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))	
+	    vty_out (vty, " neighbor %s send-community extended%s",
+		     addr, VTY_NEWLINE);
+	  else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
+	    vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
+	}
+      else
+	{
+	  if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
+	      && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
+	    vty_out (vty, " no neighbor %s send-community both%s",
+		     addr, VTY_NEWLINE);
+	  else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
+	    vty_out (vty, " no neighbor %s send-community extended%s",
+		     addr, VTY_NEWLINE);
+	  else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
+	    vty_out (vty, " no neighbor %s send-community%s",
+		     addr, VTY_NEWLINE);
+	}
+    }
+
+  /* Default information */
+  if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
+      && ! peer->af_group[afi][safi])
+    {
+      vty_out (vty, " neighbor %s default-originate", addr);
+      if (peer->default_rmap[afi][safi].name)
+	vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
+      vty_out (vty, "%s", VTY_NEWLINE);
+    }
+
+  /* Soft reconfiguration inbound. */
+  if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
+    if (! peer->af_group[afi][safi] ||
+	! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
+    vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
+	     VTY_NEWLINE);
+
+  /* maximum-prefix. */
+  if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
+    if (! peer->af_group[afi][safi]
+	|| g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
+	|| CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
+	   != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
+      vty_out (vty, " neighbor %s maximum-prefix %ld%s%s",
+	       addr, peer->pmax[afi][safi],
+	       CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
+	       ? " warning-only" : "", VTY_NEWLINE);
+
+  /* Route server client. */
+  if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
+      && ! peer->af_group[afi][safi])
+    vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
+
+  /* Allow AS in.  */
+  if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
+    if (! peer_group_active (peer)
+	|| ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
+	|| peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
+      {
+	if (peer->allowas_in[afi][safi] == 3)
+	  vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
+	else
+	  vty_out (vty, " neighbor %s allowas-in %d%s", addr,
+		   peer->allowas_in[afi][safi], VTY_NEWLINE);
+      }
+
+  /* Filter. */
+  bgp_config_write_filter (vty, peer, afi, safi);
+
+  /* atribute-unchanged. */
+  if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
+      || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
+      || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
+      && ! peer->af_group[afi][safi])
+    {
+      if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
+          && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
+          && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
+	vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
+      else
+	vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr, 
+	     (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
+	     " as-path" : "",
+	     (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
+	     " next-hop" : "",
+	     (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
+	     " med" : "", VTY_NEWLINE);
+    }
+}
+
+/* Display "address-family" configuration header. */
+void
+bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
+				int *write)
+{
+  if (*write)
+    return;
+
+  if (afi == AFI_IP && safi == SAFI_UNICAST)
+    return;
+
+  vty_out (vty, "!%s address-family ", VTY_NEWLINE);
+
+  if (afi == AFI_IP)
+    {
+      if (safi == SAFI_MULTICAST)
+	vty_out (vty, "ipv4 multicast");
+      else if (safi == SAFI_MPLS_VPN)
+	vty_out (vty, "vpnv4 unicast");
+    }
+  else if (afi == AFI_IP6)
+    vty_out (vty, "ipv6");
+
+  vty_out (vty, "%s", VTY_NEWLINE);
+
+  *write = 1;
+}
+
+/* Address family based peer configuration display.  */
+int
+bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
+			 safi_t safi)
+{
+  int write = 0;
+  struct peer *peer;
+  struct peer_group *group;
+  struct listnode *nn;
+
+  bgp_config_write_network (vty, bgp, afi, safi, &write);
+
+  bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
+
+  LIST_LOOP (bgp->group, group, nn)
+    {
+      if (group->conf->afc[afi][safi])
+	{
+	  bgp_config_write_family_header (vty, afi, safi, &write);
+	  bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
+	}
+    }
+  LIST_LOOP (bgp->peer, peer, nn)
+    {
+      if (peer->afc[afi][safi])
+	{
+	  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
+	    {
+	      bgp_config_write_family_header (vty, afi, safi, &write);
+	      bgp_config_write_peer (vty, bgp, peer, afi, safi);
+	    }
+	}
+    }
+  if (write)
+    vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
+
+  return write;
+}
+
+int
+bgp_config_write (struct vty *vty)
+{
+  int write = 0;
+  struct bgp *bgp;
+  struct peer_group *group;
+  struct peer *peer;
+  struct listnode *nn, *nm, *no;
+
+  /* BGP Multiple instance. */
+  if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
+    {    
+      vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
+      write++;
+    }
+
+  /* BGP Config type. */
+  if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
+    {    
+      vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
+      write++;
+    }
+
+  /* BGP configuration. */
+  LIST_LOOP (bm->bgp, bgp, nn)
+    {
+      if (write)
+	vty_out (vty, "!%s", VTY_NEWLINE);
+
+      /* Router bgp ASN */
+      vty_out (vty, "router bgp %d", bgp->as);
+
+      if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
+	{
+	  if (bgp->name)
+	    vty_out (vty, " view %s", bgp->name);
+	}
+      vty_out (vty, "%s", VTY_NEWLINE);
+
+      /* No Synchronization */
+      if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
+	vty_out (vty, " no synchronization%s", VTY_NEWLINE);
+
+      /* BGP fast-external-failover. */
+      if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
+	vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE); 
+
+      /* BGP router ID. */
+      if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
+	vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id), 
+		 VTY_NEWLINE);
+
+      /* BGP configuration. */
+      if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
+	vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
+
+      /* BGP default ipv4-unicast. */
+      if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
+	vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
+
+      /* BGP default local-preference. */
+      if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
+	vty_out (vty, " bgp default local-preference %d%s",
+		 bgp->default_local_pref, VTY_NEWLINE);
+
+      /* BGP client-to-client reflection. */
+      if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
+	vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
+      
+      /* BGP cluster ID. */
+      if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
+	vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
+		 VTY_NEWLINE);
+
+      /* Confederation Information */
+      if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
+	{
+	  vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
+		   VTY_NEWLINE);
+	  if (bgp->confed_peers_cnt > 0)
+	    {
+	      int i;
+
+	      vty_out (vty, " bgp confederation peers");
+
+	      for (i = 0; i < bgp->confed_peers_cnt; i++)
+		{
+		  vty_out(vty, " ");
+		  vty_out(vty, "%d", bgp->confed_peers[i]);
+		}
+
+	      vty_out (vty, "%s", VTY_NEWLINE);
+	    }
+	}
+
+      /* BGP enforce-first-as. */
+      if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
+	vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
+
+      /* BGP deterministic-med. */
+      if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
+	vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
+      
+      /* BGP bestpath method. */
+      if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
+	vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
+      if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
+	vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
+      if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
+	  || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
+	{
+	  vty_out (vty, " bgp bestpath med");
+	  if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
+	    vty_out (vty, " confed");
+	  if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
+	    vty_out (vty, " missing-as-worst");
+	  vty_out (vty, "%s", VTY_NEWLINE);
+	}
+
+      /* BGP network import check. */
+      if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
+	vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
+
+      /* BGP scan interval. */
+      bgp_config_write_scan_time (vty);
+
+      /* BGP flag dampening. */
+      if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
+	  BGP_CONFIG_DAMPENING))
+	bgp_config_write_damp (vty);
+
+      /* BGP static route configuration. */
+      bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
+
+      /* BGP redistribute configuration. */
+      bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
+
+      /* BGP timers configuration. */
+      if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
+	  && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
+	vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive, 
+		 bgp->default_holdtime, VTY_NEWLINE);
+
+      /* peer-group */
+      LIST_LOOP (bgp->group, group, nm)
+	{
+	  bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
+	}
+
+      /* Normal neighbor configuration. */
+      LIST_LOOP (bgp->peer, peer, no)
+	{
+	  if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
+	    bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
+	}
+
+      /* Distance configuration. */
+      bgp_config_write_distance (vty, bgp);
+      
+      /* No auto-summary */
+      if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
+	vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
+
+      /* IPv4 multicast configuration.  */
+      write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
+
+      /* IPv4 VPN configuration.  */
+      write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
+
+      /* IPv6 unicast configuration.  */
+      write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
+
+      write++;
+    }
+  return write;
+}
+
+void
+bgp_master_init ()
+{
+  memset (&bgp_master, 0, sizeof (struct bgp_master));
+
+  bm = &bgp_master;
+  bm->bgp = list_new ();
+  bm->port = BGP_PORT_DEFAULT;
+  bm->master = thread_master_create ();
+  bm->start_time = time (NULL);
+}
+
+void
+bgp_init ()
+{
+  void bgp_zebra_init ();
+  void bgp_route_map_init ();
+  void bgp_filter_init ();
+
+  /* BGP VTY commands installation.  */
+  bgp_vty_init ();
+
+  /* Create BGP server socket.  */
+  bgp_socket (NULL, bm->port);
+
+  /* Init zebra. */
+  bgp_zebra_init ();
+
+  /* BGP inits. */
+  bgp_attr_init ();
+  bgp_debug_init ();
+  bgp_dump_init ();
+  bgp_route_init ();
+  bgp_route_map_init ();
+  bgp_scan_init ();
+  bgp_mplsvpn_init ();
+
+  /* Access list initialize. */
+  access_list_init ();
+  access_list_add_hook (peer_distribute_update);
+  access_list_delete_hook (peer_distribute_update);
+
+  /* Filter list initialize. */
+  bgp_filter_init ();
+  as_list_add_hook (peer_aslist_update);
+  as_list_delete_hook (peer_aslist_update);
+
+  /* Prefix list initialize.*/
+  prefix_list_init ();
+  prefix_list_add_hook (peer_prefix_list_update);
+  prefix_list_delete_hook (peer_prefix_list_update);
+
+  /* Community list initialize. */
+  bgp_clist = community_list_init ();
+
+#ifdef HAVE_SNMP
+  bgp_snmp_init ();
+#endif /* HAVE_SNMP */
+}
diff --git a/bgpd/bgpd.conf.sample b/bgpd/bgpd.conf.sample
new file mode 100644
index 0000000..b6a8b6f
--- /dev/null
+++ b/bgpd/bgpd.conf.sample
@@ -0,0 +1,29 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password zebra
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+router bgp 7675
+! bgp router-id 10.0.0.1
+! network 10.0.0.0/8
+! neighbor 10.0.0.2 remote-as 7675
+! neighbor 10.0.0.2 route-map set-nexthop out
+! neighbor 10.0.0.2 ebgp-multihop
+! neighbor 10.0.0.2 next-hop-self
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file bgpd.log
+!
+log stdout
diff --git a/bgpd/bgpd.conf.sample2 b/bgpd/bgpd.conf.sample2
new file mode 100644
index 0000000..d376ad2
--- /dev/null
+++ b/bgpd/bgpd.conf.sample2
@@ -0,0 +1,77 @@
+!
+! Zebra configuration saved from vty
+!   2002/07/01 03:16:33
+!
+hostname bgpd
+password zebra
+log file bgpd.log
+log stdout
+!
+router bgp 7675
+ no bgp default ipv4-unicast
+ neighbor 3ffe:506:1000::2 remote-as 7675
+ neighbor fe80::200:c0ff:fe30:9be3 remote-as 9377
+ neighbor fe80::200:c0ff:fe30:9be3 interface sit3
+ neighbor fe80::210:5aff:fe6b:3cee remote-as 7675
+ neighbor fe80::210:5aff:fe6b:3cee interface eth0
+ neighbor fe80::290:27ff:fe51:84c7 remote-as 4691
+ neighbor fe80::290:27ff:fe51:84c7 description DTI 
+ neighbor fe80::290:27ff:fe51:84c7 interface sit7
+ neighbor fe80::2a0:c9ff:fec8:82ec remote-as 7530
+ neighbor fe80::2a0:c9ff:fec8:82ec description IRI 
+ neighbor fe80::2a0:c9ff:fec8:82ec interface sit8
+ neighbor fe80::2e0:18ff:fe98:2725 remote-as 2500
+ neighbor fe80::2e0:18ff:fe98:2725 description WIDE 
+ neighbor fe80::2e0:18ff:fe98:2725 interface sit5
+ neighbor fe80::2e0:18ff:fea8:bf5 remote-as 65000
+ neighbor fe80::2e0:18ff:fea8:bf5 interface sit6
+!
+ address-family ipv6
+ network 3ffe:506::/33
+ network 3ffe:1800:e800::/40
+ aggregate-address 3ffe:506::/32
+ redistribute connected
+ neighbor 3ffe:506:1000::2 activate
+ neighbor fe80::200:c0ff:fe30:9be3 activate
+ neighbor fe80::200:c0ff:fe30:9be3 route-map set-nexthop out
+ neighbor fe80::210:5aff:fe6b:3cee activate
+ neighbor fe80::290:27ff:fe51:84c7 activate
+ neighbor fe80::290:27ff:fe51:84c7 route-map set-nexthop out
+ neighbor fe80::2a0:c9ff:fec8:82ec activate
+ neighbor fe80::2a0:c9ff:fec8:82ec route-map set-nexthop out
+ neighbor fe80::2e0:18ff:fe98:2725 activate
+ neighbor fe80::2e0:18ff:fe98:2725 distribute-list nla1 out
+ neighbor fe80::2e0:18ff:fe98:2725 route-map set-nexthop out
+ neighbor fe80::2e0:18ff:fea8:bf5 activate
+ neighbor fe80::2e0:18ff:fea8:bf5 route-map set-nexthop out
+ exit-address-family
+!
+ipv6 access-list all permit any
+ipv6 access-list nla1 deny 3ffe:506::/33
+ipv6 access-list nla1 permit 3ffe:506::/32
+ipv6 access-list nla1 deny any
+ipv6 access-list ntt-nla1 permit 3ffe:1800:0:ffff::c/127
+ipv6 access-list ntt-nla1 deny 3ffe:1800:e800::/41
+ipv6 access-list ntt-nla1 permit 3ffe:1800:e800::/40
+ipv6 access-list ntt-nla1 deny any
+!
+ipv6 prefix-list 6bone-filter seq 5 permit 3ffe::/17 ge 24 le 24
+ipv6 prefix-list 6bone-filter seq 10 permit 3ffe:8000::/17 ge 28 le 28
+ipv6 prefix-list 6bone-filter seq 12 deny 3ffe::/16
+ipv6 prefix-list 6bone-filter seq 15 permit 2000::/3 ge 16 le 16
+ipv6 prefix-list 6bone-filter seq 20 permit 2001::/16 ge 35 le 35
+!
+route-map set-nexthop permit 10
+ match ipv6 address all
+ set ipv6 next-hop global 3ffe:506::1
+ set ipv6 next-hop local fe80::cbb5:591a
+ set ip next-hop 203.181.89.26
+ set community 7675:0
+!
+route-map set-link-local permit 10
+ match ipv6 address all
+ set ipv6 next-hop local fe80::cbb5:591a
+ set ipv6 next-hop global 3ffe:1800:0:ffff::d
+!
+line vty
+!
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
new file mode 100644
index 0000000..01d4721
--- /dev/null
+++ b/bgpd/bgpd.h
@@ -0,0 +1,824 @@
+/* BGP message definition header.
+   Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
+
+This file is part of GNU Zebra.
+
+GNU Zebra is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU Zebra is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Zebra; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+/* For union sockunion.  */
+#include "sockunion.h"
+
+/* Typedef BGP specific types.  */
+typedef u_int16_t as_t;
+typedef u_int16_t bgp_size_t;
+
+/* BGP master for system wide configurations and variables.  */
+struct bgp_master
+{
+  /* BGP instance list.  */
+  struct list *bgp;
+
+  /* BGP thread master.  */
+  struct thread_master *master;
+
+  /* BGP port number.  */
+  u_int16_t port;
+
+  /* BGP start time.  */
+  time_t start_time;
+
+  /* Various BGP global configuration.  */
+  u_char options;
+#define BGP_OPT_NO_FIB                   (1 << 0)
+#define BGP_OPT_MULTIPLE_INSTANCE        (1 << 1)
+#define BGP_OPT_CONFIG_CISCO             (1 << 2)
+};
+
+/* BGP instance structure.  */
+struct bgp 
+{
+  /* AS number of this BGP instance.  */
+  as_t as;
+
+  /* Name of this BGP instance.  */
+  char *name;
+
+  /* Self peer.  */
+  struct peer *peer_self;
+
+  /* BGP peer. */
+  struct list *peer;
+
+  /* BGP peer group.  */
+  struct list *group;
+
+  /* BGP configuration.  */
+  u_int16_t config;
+#define BGP_CONFIG_ROUTER_ID              (1 << 0)
+#define BGP_CONFIG_CLUSTER_ID             (1 << 1)
+#define BGP_CONFIG_CONFEDERATION          (1 << 2)
+#define BGP_CONFIG_DEFAULT_LOCAL_PREF     (1 << 3)
+
+  /* BGP router identifier.  */
+  struct in_addr router_id;
+
+  /* BGP route reflector cluster ID.  */
+  struct in_addr cluster_id;
+
+  /* BGP confederation information.  */
+  as_t confed_id;
+  as_t *confed_peers;
+  int confed_peers_cnt;
+
+  /* BGP flags. */
+  u_int16_t flags;
+#define BGP_FLAG_ALWAYS_COMPARE_MED       (1 << 0)
+#define BGP_FLAG_DETERMINISTIC_MED        (1 << 1)
+#define BGP_FLAG_MED_MISSING_AS_WORST     (1 << 2)
+#define BGP_FLAG_MED_CONFED               (1 << 3)
+#define BGP_FLAG_NO_DEFAULT_IPV4          (1 << 4)
+#define BGP_FLAG_NO_CLIENT_TO_CLIENT      (1 << 5)
+#define BGP_FLAG_ENFORCE_FIRST_AS         (1 << 6)
+#define BGP_FLAG_COMPARE_ROUTER_ID        (1 << 7)
+#define BGP_FLAG_ASPATH_IGNORE            (1 << 8)
+#define BGP_FLAG_IMPORT_CHECK             (1 << 9)
+#define BGP_FLAG_NO_FAST_EXT_FAILOVER     (1 << 10)
+
+  /* BGP Per AF flags */
+  u_int16_t af_flags[AFI_MAX][SAFI_MAX];
+#define BGP_CONFIG_DAMPENING              (1 << 0)
+
+  /* Static route configuration.  */
+  struct bgp_table *route[AFI_MAX][SAFI_MAX];
+
+  /* Aggregate address configuration.  */
+  struct bgp_table *aggregate[AFI_MAX][SAFI_MAX];
+
+  /* BGP routing information base.  */
+  struct bgp_table *rib[AFI_MAX][SAFI_MAX];
+
+  /* BGP redistribute configuration. */
+  u_char redist[AFI_MAX][ZEBRA_ROUTE_MAX];
+
+  /* BGP redistribute metric configuration. */
+  u_char redist_metric_flag[AFI_MAX][ZEBRA_ROUTE_MAX];
+  u_int32_t redist_metric[AFI_MAX][ZEBRA_ROUTE_MAX];
+
+  /* BGP redistribute route-map.  */
+  struct
+  {
+    char *name;
+    struct route_map *map;
+  } rmap[AFI_MAX][ZEBRA_ROUTE_MAX];
+
+  /* BGP distance configuration.  */
+  u_char distance_ebgp;
+  u_char distance_ibgp;
+  u_char distance_local;
+  
+  /* BGP default local-preference.  */
+  u_int32_t default_local_pref;
+
+  /* BGP default timer.  */
+  u_int32_t default_holdtime;
+  u_int32_t default_keepalive;
+};
+
+/* BGP peer-group support. */
+struct peer_group
+{
+  /* Name of the peer-group. */
+  char *name;
+
+  /* Pointer to BGP.  */
+  struct bgp *bgp;
+  
+  /* Peer-group client list. */
+  struct list *peer;
+
+  /* Peer-group config */
+  struct peer *conf;
+};
+
+/* BGP Notify message format. */
+struct bgp_notify 
+{
+  u_char code;
+  u_char subcode;
+  char *data;
+  bgp_size_t length;
+};
+
+/* Next hop self address. */
+struct bgp_nexthop
+{
+  struct interface *ifp;
+  struct in_addr v4;
+#ifdef HAVE_IPV6
+  struct in6_addr v6_global;
+  struct in6_addr v6_local;
+#endif /* HAVE_IPV6 */  
+};
+
+/* BGP router distinguisher value.  */
+#define BGP_RD_SIZE                8
+
+struct bgp_rd
+{
+  u_char val[BGP_RD_SIZE];
+};
+
+/* BGP filter structure. */
+struct bgp_filter
+{
+  /* Distribute-list.  */
+  struct 
+  {
+    char *name;
+    struct access_list *alist;
+  } dlist[FILTER_MAX];
+
+  /* Prefix-list.  */
+  struct
+  {
+    char *name;
+    struct prefix_list *plist;
+  } plist[FILTER_MAX];
+
+  /* Filter-list.  */
+  struct
+  {
+    char *name;
+    struct as_list *aslist;
+  } aslist[FILTER_MAX];
+
+  /* Route-map.  */
+  struct
+  {
+    char *name;
+    struct route_map *map;
+  } map[FILTER_MAX];
+
+  /* Unsuppress-map.  */
+  struct
+  {
+    char *name;
+    struct route_map *map;
+  } usmap;
+};
+
+/* BGP neighbor structure. */
+struct peer
+{
+  /* BGP structure.  */
+  struct bgp *bgp;
+
+  /* BGP peer group.  */
+  struct peer_group *group;
+  u_char af_group[AFI_MAX][SAFI_MAX];
+
+  /* Peer's remote AS number. */
+  as_t as;			
+
+  /* Peer's local AS number. */
+  as_t local_as;
+
+  /* Peer's Change local AS number. */
+  as_t change_local_as;
+
+  /* Remote router ID. */
+  struct in_addr remote_id;
+
+  /* Local router ID. */
+  struct in_addr local_id;
+
+  /* Packet receive and send buffer. */
+  struct stream *ibuf;
+  struct stream_fifo *obuf;
+  struct stream *work;
+
+  /* Status of the peer. */
+  int status;
+  int ostatus;
+
+  /* Peer information */
+  int fd;			/* File descriptor */
+  int ttl;			/* TTL of TCP connection to the peer. */
+  char *desc;			/* Description of the peer. */
+  unsigned short port;          /* Destination port for peer */
+  char *host;			/* Printable address of the peer. */
+  union sockunion su;		/* Sockunion address of the peer. */
+  time_t uptime;		/* Last Up/Down time */
+  time_t readtime;		/* Last read time */
+  
+  unsigned int ifindex;		/* ifindex of the BGP connection. */
+  char *ifname;			/* bind interface name. */
+  char *update_if;
+  union sockunion *update_source;
+  struct zlog *log;
+  u_char version;		/* Peer BGP version. */
+
+  union sockunion *su_local;	/* Sockunion of local address.  */
+  union sockunion *su_remote;	/* Sockunion of remote address.  */
+  int shared_network;		/* Is this peer shared same network. */
+  struct bgp_nexthop nexthop;	/* Nexthop */
+
+  /* Peer address family configuration. */
+  u_char afc[AFI_MAX][SAFI_MAX];
+  u_char afc_nego[AFI_MAX][SAFI_MAX];
+  u_char afc_adv[AFI_MAX][SAFI_MAX];
+  u_char afc_recv[AFI_MAX][SAFI_MAX];
+
+  /* Capability Flags.*/
+  u_char cap;
+#define PEER_CAP_REFRESH_ADV                (1 << 0) /* refresh advertised */
+#define PEER_CAP_REFRESH_OLD_RCV            (1 << 1) /* refresh old received */
+#define PEER_CAP_REFRESH_NEW_RCV            (1 << 2) /* refresh rfc received */
+#define PEER_CAP_DYNAMIC_ADV                (1 << 3) /* dynamic advertised */
+#define PEER_CAP_DYNAMIC_RCV                (1 << 4) /* dynamic received */
+
+  /* Capability Flags.*/
+  u_int16_t af_cap[AFI_MAX][SAFI_MAX];
+#define PEER_CAP_ORF_PREFIX_SM_ADV          (1 << 0) /* send-mode advertised */
+#define PEER_CAP_ORF_PREFIX_RM_ADV          (1 << 1) /* receive-mode advertised */
+#define PEER_CAP_ORF_PREFIX_SM_RCV          (1 << 2) /* send-mode received */
+#define PEER_CAP_ORF_PREFIX_RM_RCV          (1 << 3) /* receive-mode received */
+#define PEER_CAP_ORF_PREFIX_SM_OLD_RCV      (1 << 4) /* send-mode received */
+#define PEER_CAP_ORF_PREFIX_RM_OLD_RCV      (1 << 5) /* receive-mode received */
+
+  /* Global configuration flags. */
+  u_int32_t flags;
+#define PEER_FLAG_PASSIVE                   (1 << 0) /* passive mode */
+#define PEER_FLAG_SHUTDOWN                  (1 << 1) /* shutdown */
+#define PEER_FLAG_DONT_CAPABILITY           (1 << 2) /* dont-capability */
+#define PEER_FLAG_OVERRIDE_CAPABILITY       (1 << 3) /* override-capability */
+#define PEER_FLAG_STRICT_CAP_MATCH          (1 << 4) /* strict-match */
+#define PEER_FLAG_NO_ROUTE_REFRESH_CAP      (1 << 5) /* route-refresh */
+#define PEER_FLAG_DYNAMIC_CAPABILITY        (1 << 6) /* dynamic capability */
+#define PEER_FLAG_ENFORCE_MULTIHOP          (1 << 7) /* enforce-multihop */
+#define PEER_FLAG_LOCAL_AS_NO_PREPEND       (1 << 8) /* local-as no-prepend */
+
+  /* Per AF configuration flags. */
+  u_int32_t af_flags[AFI_MAX][SAFI_MAX];
+#define PEER_FLAG_SEND_COMMUNITY            (1 << 0) /* send-community */
+#define PEER_FLAG_SEND_EXT_COMMUNITY        (1 << 1) /* send-community ext. */
+#define PEER_FLAG_NEXTHOP_SELF              (1 << 2) /* next-hop-self */
+#define PEER_FLAG_REFLECTOR_CLIENT          (1 << 3) /* reflector-client */
+#define PEER_FLAG_RSERVER_CLIENT            (1 << 4) /* route-server-client */
+#define PEER_FLAG_SOFT_RECONFIG             (1 << 5) /* soft-reconfiguration */
+#define PEER_FLAG_AS_PATH_UNCHANGED         (1 << 6) /* transparent-as */
+#define PEER_FLAG_NEXTHOP_UNCHANGED         (1 << 7) /* transparent-next-hop */
+#define PEER_FLAG_MED_UNCHANGED             (1 << 8) /* transparent-next-hop */
+#define PEER_FLAG_DEFAULT_ORIGINATE         (1 << 9) /* default-originate */
+#define PEER_FLAG_REMOVE_PRIVATE_AS         (1 << 10) /* remove-private-as */
+#define PEER_FLAG_ALLOWAS_IN                (1 << 11) /* set allowas-in */
+#define PEER_FLAG_ORF_PREFIX_SM             (1 << 12) /* orf capability send-mode */
+#define PEER_FLAG_ORF_PREFIX_RM             (1 << 13) /* orf capability receive-mode */
+#define PEER_FLAG_MAX_PREFIX                (1 << 14) /* maximum prefix */
+#define PEER_FLAG_MAX_PREFIX_WARNING        (1 << 15) /* maximum prefix warning-only */
+
+  /* default-originate route-map.  */
+  struct
+  {
+    char *name;
+    struct route_map *map;
+  } default_rmap[AFI_MAX][SAFI_MAX];
+
+  /* Peer status flags. */
+  u_int16_t sflags;
+#define PEER_STATUS_ACCEPT_PEER	      (1 << 0) /* accept peer */
+#define PEER_STATUS_PREFIX_OVERFLOW   (1 << 1) /* prefix-overflow */
+#define PEER_STATUS_CAPABILITY_OPEN   (1 << 2) /* capability open send */
+#define PEER_STATUS_HAVE_ACCEPT       (1 << 3) /* accept peer's parent */
+#define PEER_STATUS_GROUP             (1 << 4) /* peer-group conf */
+
+  /* Peer status af flags. */
+  u_int16_t af_sflags[AFI_MAX][SAFI_MAX];
+#define PEER_STATUS_ORF_PREFIX_SEND   (1 << 0) /* prefix-list send peer */
+#define PEER_STATUS_ORF_WAIT_REFRESH  (1 << 1) /* wait refresh received peer */
+#define PEER_STATUS_DEFAULT_ORIGINATE (1 << 2) /* default-originate peer */
+
+  /* Default attribute value for the peer. */
+  u_int32_t config;
+#define PEER_CONFIG_WEIGHT            (1 << 0) /* Default weight. */
+#define PEER_CONFIG_TIMER             (1 << 1) /* keepalive & holdtime */
+#define PEER_CONFIG_CONNECT           (1 << 2) /* connect */
+#define PEER_CONFIG_ROUTEADV          (1 << 3) /* route advertise */
+  u_int32_t weight;
+  u_int32_t holdtime;
+  u_int32_t keepalive;
+  u_int32_t connect;
+  u_int32_t routeadv;
+
+  /* Timer values. */
+  u_int32_t v_start;
+  u_int32_t v_connect;
+  u_int32_t v_holdtime;
+  u_int32_t v_keepalive;
+  u_int32_t v_asorig;
+  u_int32_t v_routeadv;
+
+  /* Threads. */
+  struct thread *t_read;
+  struct thread *t_write;
+  struct thread *t_start;
+  struct thread *t_connect;
+  struct thread *t_holdtime;
+  struct thread *t_keepalive;
+  struct thread *t_asorig;
+  struct thread *t_routeadv;
+
+  /* Statistics field */
+  u_int32_t open_in;		/* Open message input count */
+  u_int32_t open_out;		/* Open message output count */
+  u_int32_t update_in;		/* Update message input count */
+  u_int32_t update_out;		/* Update message ouput count */
+  time_t update_time;		/* Update message received time. */
+  u_int32_t keepalive_in;	/* Keepalive input count */
+  u_int32_t keepalive_out;	/* Keepalive output count */
+  u_int32_t notify_in;		/* Notify input count */
+  u_int32_t notify_out;		/* Notify output count */
+  u_int32_t refresh_in;		/* Route Refresh input count */
+  u_int32_t refresh_out;	/* Route Refresh output count */
+  u_int32_t dynamic_cap_in;	/* Dynamic Capability input count.  */
+  u_int32_t dynamic_cap_out;	/* Dynamic Capability output count.  */
+
+  /* BGP state count */
+  u_int32_t established;	/* Established */
+  u_int32_t dropped;		/* Dropped */
+
+  /* Syncronization list and time.  */
+  struct bgp_synchronize *sync[AFI_MAX][SAFI_MAX];
+  time_t synctime;
+
+  /* Send prefix count. */
+  unsigned long scount[AFI_MAX][SAFI_MAX];
+
+  /* Announcement attribute hash.  */
+  struct hash *hash[AFI_MAX][SAFI_MAX];
+
+  /* Notify data. */
+  struct bgp_notify notify;
+
+  /* Whole packet size to be read. */
+  unsigned long packet_size;
+
+  /* Filter structure. */
+  struct bgp_filter filter[AFI_MAX][SAFI_MAX];
+
+  /* ORF Prefix-list */
+  struct prefix_list *orf_plist[AFI_MAX][SAFI_MAX];
+
+  /* Prefix count. */
+  unsigned long pcount[AFI_MAX][SAFI_MAX];
+
+  /* Max prefix count. */
+  unsigned long pmax[AFI_MAX][SAFI_MAX];
+
+  /* allowas-in. */
+  char allowas_in[AFI_MAX][SAFI_MAX];
+};
+
+/* This structure's member directly points incoming packet data
+   stream. */
+struct bgp_nlri
+{
+  /* AFI.  */
+  afi_t afi;
+
+  /* SAFI.  */
+  safi_t safi;
+
+  /* Pointer to NLRI byte stream.  */
+  u_char *nlri;
+
+  /* Length of whole NLRI.  */
+  bgp_size_t length;
+};
+
+/* BGP versions.  */
+#define BGP_VERSION_4		                 4
+#define BGP_VERSION_MP_4_DRAFT_00               40
+
+/* Default BGP port number.  */
+#define BGP_PORT_DEFAULT                       179
+
+/* BGP message header and packet size.  */
+#define BGP_MARKER_SIZE		                16
+#define BGP_HEADER_SIZE		                19
+#define BGP_MAX_PACKET_SIZE                   4096
+
+/* BGP minimum message size.  */
+#define BGP_MSG_OPEN_MIN_SIZE                   (BGP_HEADER_SIZE + 10)
+#define BGP_MSG_UPDATE_MIN_SIZE                 (BGP_HEADER_SIZE + 4)
+#define BGP_MSG_NOTIFY_MIN_SIZE                 (BGP_HEADER_SIZE + 2)
+#define BGP_MSG_KEEPALIVE_MIN_SIZE              (BGP_HEADER_SIZE + 0)
+#define BGP_MSG_ROUTE_REFRESH_MIN_SIZE          (BGP_HEADER_SIZE + 4)
+#define BGP_MSG_CAPABILITY_MIN_SIZE             (BGP_HEADER_SIZE + 3)
+
+/* BGP message types.  */
+#define	BGP_MSG_OPEN		                 1
+#define	BGP_MSG_UPDATE		                 2
+#define	BGP_MSG_NOTIFY		                 3
+#define	BGP_MSG_KEEPALIVE	                 4
+#define BGP_MSG_ROUTE_REFRESH_NEW                5
+#define BGP_MSG_CAPABILITY                       6
+#define BGP_MSG_ROUTE_REFRESH_OLD              128
+
+/* BGP open optional parameter.  */
+#define BGP_OPEN_OPT_AUTH                        1
+#define BGP_OPEN_OPT_CAP                         2
+
+/* BGP4 attribute type codes.  */
+#define BGP_ATTR_ORIGIN                          1
+#define BGP_ATTR_AS_PATH                         2
+#define BGP_ATTR_NEXT_HOP                        3
+#define BGP_ATTR_MULTI_EXIT_DISC                 4
+#define BGP_ATTR_LOCAL_PREF                      5
+#define BGP_ATTR_ATOMIC_AGGREGATE                6
+#define BGP_ATTR_AGGREGATOR                      7
+#define BGP_ATTR_COMMUNITIES                     8
+#define BGP_ATTR_ORIGINATOR_ID                   9
+#define BGP_ATTR_CLUSTER_LIST                   10
+#define BGP_ATTR_DPA                            11
+#define BGP_ATTR_ADVERTISER                     12
+#define BGP_ATTR_RCID_PATH                      13
+#define BGP_ATTR_MP_REACH_NLRI                  14
+#define BGP_ATTR_MP_UNREACH_NLRI                15
+#define BGP_ATTR_EXT_COMMUNITIES                16
+
+/* BGP update origin.  */
+#define BGP_ORIGIN_IGP                           0
+#define BGP_ORIGIN_EGP                           1
+#define BGP_ORIGIN_INCOMPLETE                    2
+
+/* BGP notify message codes.  */
+#define BGP_NOTIFY_HEADER_ERR                    1
+#define BGP_NOTIFY_OPEN_ERR                      2
+#define BGP_NOTIFY_UPDATE_ERR                    3
+#define BGP_NOTIFY_HOLD_ERR                      4
+#define BGP_NOTIFY_FSM_ERR                       5
+#define BGP_NOTIFY_CEASE                         6
+#define BGP_NOTIFY_CAPABILITY_ERR                7
+#define BGP_NOTIFY_MAX	                         8
+
+/* BGP_NOTIFY_HEADER_ERR sub codes.  */
+#define BGP_NOTIFY_HEADER_NOT_SYNC               1
+#define BGP_NOTIFY_HEADER_BAD_MESLEN             2
+#define BGP_NOTIFY_HEADER_BAD_MESTYPE            3
+#define BGP_NOTIFY_HEADER_MAX                    4
+
+/* BGP_NOTIFY_OPEN_ERR sub codes.  */
+#define BGP_NOTIFY_OPEN_UNSUP_VERSION            1
+#define BGP_NOTIFY_OPEN_BAD_PEER_AS              2
+#define BGP_NOTIFY_OPEN_BAD_BGP_IDENT            3
+#define BGP_NOTIFY_OPEN_UNSUP_PARAM              4
+#define BGP_NOTIFY_OPEN_AUTH_FAILURE             5
+#define BGP_NOTIFY_OPEN_UNACEP_HOLDTIME          6
+#define BGP_NOTIFY_OPEN_UNSUP_CAPBL              7
+#define BGP_NOTIFY_OPEN_MAX                      8
+
+/* BGP_NOTIFY_UPDATE_ERR sub codes.  */
+#define BGP_NOTIFY_UPDATE_MAL_ATTR               1
+#define BGP_NOTIFY_UPDATE_UNREC_ATTR             2
+#define BGP_NOTIFY_UPDATE_MISS_ATTR              3
+#define BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR          4
+#define BGP_NOTIFY_UPDATE_ATTR_LENG_ERR          5
+#define BGP_NOTIFY_UPDATE_INVAL_ORIGIN           6
+#define BGP_NOTIFY_UPDATE_AS_ROUTE_LOOP          7
+#define BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP         8
+#define BGP_NOTIFY_UPDATE_OPT_ATTR_ERR           9
+#define BGP_NOTIFY_UPDATE_INVAL_NETWORK         10
+#define BGP_NOTIFY_UPDATE_MAL_AS_PATH           11
+#define BGP_NOTIFY_UPDATE_MAX                   12
+
+/* BGP_NOTIFY_CEASE sub codes (draft-ietf-idr-cease-subcode-00).  */
+#define BGP_NOTIFY_CEASE_MAX_PREFIX              1
+#define BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN          2
+#define BGP_NOTIFY_CEASE_PEER_UNCONFIG           3
+#define BGP_NOTIFY_CEASE_ADMIN_RESET             4
+#define BGP_NOTIFY_CEASE_CONNECT_REJECT          5
+#define BGP_NOTIFY_CEASE_CONFIG_CHANGE           6
+#define BGP_NOTIFY_CEASE_MAX                     7
+
+/* BGP_NOTIFY_CAPABILITY_ERR sub codes (draft-ietf-idr-dynamic-cap-02). */
+#define BGP_NOTIFY_CAPABILITY_INVALID_ACTION     1
+#define BGP_NOTIFY_CAPABILITY_INVALID_LENGTH     2
+#define BGP_NOTIFY_CAPABILITY_MALFORMED_CODE     3
+#define BGP_NOTIFY_CAPABILITY_MAX                4
+
+/* BGP finite state machine status.  */
+#define Idle                                     1
+#define Connect                                  2
+#define Active                                   3
+#define OpenSent                                 4
+#define OpenConfirm                              5
+#define Established                              6
+#define BGP_STATUS_MAX                           7
+
+/* BGP finite state machine events.  */
+#define BGP_Start                                1
+#define BGP_Stop                                 2
+#define TCP_connection_open                      3
+#define TCP_connection_closed                    4
+#define TCP_connection_open_failed               5
+#define TCP_fatal_error                          6
+#define ConnectRetry_timer_expired               7
+#define Hold_Timer_expired                       8
+#define KeepAlive_timer_expired                  9
+#define Receive_OPEN_message                    10
+#define Receive_KEEPALIVE_message               11
+#define Receive_UPDATE_message                  12
+#define Receive_NOTIFICATION_message            13
+#define BGP_EVENTS_MAX                          14
+
+/* BGP timers default value.  */
+#define BGP_INIT_START_TIMER                     5
+#define BGP_ERROR_START_TIMER                   30
+#define BGP_DEFAULT_HOLDTIME                   180
+#define BGP_DEFAULT_KEEPALIVE                   60 
+#define BGP_DEFAULT_ASORIGINATE                 15
+#define BGP_DEFAULT_EBGP_ROUTEADV               30
+#define BGP_DEFAULT_IBGP_ROUTEADV                5
+#define BGP_CLEAR_CONNECT_RETRY                 20
+#define BGP_DEFAULT_CONNECT_RETRY              120
+
+/* BGP default local preference.  */
+#define BGP_DEFAULT_LOCAL_PREF                 100
+
+/* SAFI which used in open capability negotiation.  */
+#define BGP_SAFI_VPNV4                         128
+#define BGP_SAFI_VPNV6                         129
+
+/* Max TTL value.  */
+#define TTL_MAX                                255
+
+/* BGP uptime string length.  */
+#define BGP_UPTIME_LEN 25
+
+/* Default configuration settings for bgpd.  */
+#define BGP_VTY_PORT                          2605
+#define BGP_VTYSH_PATH                "/tmp/.bgpd"
+#define BGP_DEFAULT_CONFIG             "bgpd.conf"
+
+/* Check AS path loop when we send NLRI.  */
+/* #define BGP_SEND_ASPATH_CHECK */
+
+/* IBGP/EBGP identifier.  We also have a CONFED peer, which is to say,
+   a peer who's AS is part of our Confederation.  */
+enum
+{
+  BGP_PEER_IBGP,
+  BGP_PEER_EBGP,
+  BGP_PEER_INTERNAL,
+  BGP_PEER_CONFED
+};
+
+/* Flag for peer_clear_soft().  */
+enum bgp_clear_type
+{
+  BGP_CLEAR_SOFT_NONE,
+  BGP_CLEAR_SOFT_OUT,
+  BGP_CLEAR_SOFT_IN,
+  BGP_CLEAR_SOFT_BOTH,
+  BGP_CLEAR_SOFT_IN_ORF_PREFIX
+};
+
+/* Macros. */
+#define BGP_INPUT(P)         ((P)->ibuf)
+#define BGP_INPUT_PNT(P)     (STREAM_PNT(BGP_INPUT(P)))
+
+/* Macro to check BGP information is alive or not.  */
+#define BGP_INFO_HOLDDOWN(BI)                         \
+  (! CHECK_FLAG ((BI)->flags, BGP_INFO_VALID)         \
+   || CHECK_FLAG ((BI)->flags, BGP_INFO_HISTORY)      \
+   || CHECK_FLAG ((BI)->flags, BGP_INFO_DAMPED))
+
+/* Count prefix size from mask length */
+#define PSIZE(a) (((a) + 7) / (8))
+
+/* BGP error codes.  */
+#define BGP_SUCCESS                               0
+#define BGP_ERR_INVALID_VALUE                    -1
+#define BGP_ERR_INVALID_FLAG                     -2
+#define BGP_ERR_INVALID_AS                       -3
+#define BGP_ERR_INVALID_BGP                      -4
+#define BGP_ERR_PEER_GROUP_MEMBER                -5
+#define BGP_ERR_MULTIPLE_INSTANCE_USED           -6
+#define BGP_ERR_PEER_GROUP_MEMBER_EXISTS         -7
+#define BGP_ERR_PEER_BELONGS_TO_GROUP            -8
+#define BGP_ERR_PEER_GROUP_AF_UNCONFIGURED       -9
+#define BGP_ERR_PEER_GROUP_NO_REMOTE_AS         -10
+#define BGP_ERR_PEER_GROUP_CANT_CHANGE          -11
+#define BGP_ERR_PEER_GROUP_MISMATCH             -12
+#define BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT  -13
+#define BGP_ERR_MULTIPLE_INSTANCE_NOT_SET       -14
+#define BGP_ERR_AS_MISMATCH                     -15
+#define BGP_ERR_PEER_INACTIVE                   -16
+#define BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER   -17
+#define BGP_ERR_PEER_GROUP_HAS_THE_FLAG         -18
+#define BGP_ERR_PEER_FLAG_CONFLICT              -19
+#define BGP_ERR_PEER_GROUP_SHUTDOWN             -20
+#define BGP_ERR_PEER_FILTER_CONFLICT            -21
+#define BGP_ERR_NOT_INTERNAL_PEER               -22
+#define BGP_ERR_REMOVE_PRIVATE_AS               -23
+#define BGP_ERR_AF_UNCONFIGURED                 -24
+#define BGP_ERR_SOFT_RECONFIG_UNCONFIGURED      -25
+#define BGP_ERR_INSTANCE_MISMATCH               -26
+#define BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP  -27
+#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS    -28
+#define BGP_ERR_MAX                             -29
+
+extern struct bgp_master *bm;
+
+extern struct thread_master *master;
+
+/* Prototypes. */
+void bgp_terminate (void);
+void bgp_reset (void);
+void bgp_zclient_reset ();
+int bgp_nexthop_set (union sockunion *, union sockunion *, 
+		     struct bgp_nexthop *, struct peer *);
+struct bgp *bgp_get_default ();
+struct bgp *bgp_lookup (as_t, char *);
+struct bgp *bgp_lookup_by_name (char *);
+struct peer *peer_lookup (struct bgp *, union sockunion *);
+struct peer_group *peer_group_lookup (struct bgp *, char *);
+struct peer_group *peer_group_get (struct bgp *, char *);
+struct peer *peer_lookup_with_open (union sockunion *, as_t, struct in_addr *,
+				    int *);
+int peer_sort (struct peer *peer);
+int peer_active (struct peer *);
+int peer_active_nego (struct peer *);
+struct peer *peer_create_accept (struct bgp *);
+char *peer_uptime (time_t, char *, size_t);
+void bgp_config_write_family_header (struct vty *, afi_t, safi_t, int *);
+
+void bgp_master_init ();
+
+void bgp_init ();
+
+int bgp_option_set (int);
+int bgp_option_unset (int);
+int bgp_option_check (int);
+
+int bgp_get (struct bgp **, as_t *, char *);
+int bgp_delete (struct bgp *);
+
+int bgp_flag_set (struct bgp *, int);
+int bgp_flag_unset (struct bgp *, int);
+int bgp_flag_check (struct bgp *, int);
+
+int bgp_router_id_set (struct bgp *, struct in_addr *);
+int bgp_router_id_unset (struct bgp *);
+
+int bgp_cluster_id_set (struct bgp *, struct in_addr *);
+int bgp_cluster_id_unset (struct bgp *);
+
+int bgp_confederation_id_set (struct bgp *, as_t);
+int bgp_confederation_id_unset (struct bgp *);
+int bgp_confederation_peers_check (struct bgp *, as_t);
+
+int bgp_confederation_peers_add (struct bgp *, as_t);
+int bgp_confederation_peers_remove (struct bgp *, as_t);
+
+int bgp_timers_set (struct bgp *, u_int32_t, u_int32_t);
+int bgp_timers_unset (struct bgp *);
+
+int bgp_default_local_preference_set (struct bgp *, u_int32_t);
+int bgp_default_local_preference_unset (struct bgp *);
+
+int peer_remote_as (struct bgp *, union sockunion *, as_t *, afi_t, safi_t);
+int peer_group_remote_as (struct bgp *, char *, as_t *);
+int peer_delete (struct peer *peer);
+int peer_group_delete (struct peer_group *);
+int peer_group_remote_as_delete (struct peer_group *);
+
+int peer_activate (struct peer *, afi_t, safi_t);
+int peer_deactivate (struct peer *, afi_t, safi_t);
+
+int peer_group_bind (struct bgp *, union sockunion *, struct peer_group *,
+		     afi_t, safi_t, as_t *);
+int peer_group_unbind (struct bgp *, struct peer *, struct peer_group *,
+		       afi_t, safi_t);
+
+int peer_flag_set (struct peer *, u_int32_t);
+int peer_flag_unset (struct peer *, u_int32_t);
+
+int peer_af_flag_set (struct peer *, afi_t, safi_t, u_int32_t);
+int peer_af_flag_unset (struct peer *, afi_t, safi_t, u_int32_t);
+int peer_af_flag_check (struct peer *, afi_t, safi_t, u_int32_t);
+
+int peer_ebgp_multihop_set (struct peer *, int);
+int peer_ebgp_multihop_unset (struct peer *);
+
+int peer_description_set (struct peer *, char *);
+int peer_description_unset (struct peer *);
+
+int peer_update_source_if_set (struct peer *, char *);
+int peer_update_source_addr_set (struct peer *, union sockunion *);
+int peer_update_source_unset (struct peer *);
+
+int peer_default_originate_set (struct peer *, afi_t, safi_t, char *);
+int peer_default_originate_unset (struct peer *, afi_t, safi_t);
+
+int peer_port_set (struct peer *, u_int16_t);
+int peer_port_unset (struct peer *);
+
+int peer_weight_set (struct peer *, u_int16_t);
+int peer_weight_unset (struct peer *);
+
+int peer_timers_set (struct peer *, u_int32_t, u_int32_t);
+int peer_timers_unset (struct peer *);
+
+int peer_timers_connect_set (struct peer *, u_int32_t);
+int peer_timers_connect_unset (struct peer *);
+
+int peer_advertise_interval_set (struct peer *, u_int32_t);
+int peer_advertise_interval_unset (struct peer *);
+
+int peer_version_set (struct peer *, int);
+int peer_version_unset (struct peer *);
+
+int peer_interface_set (struct peer *, char *);
+int peer_interface_unset (struct peer *);
+
+int peer_distribute_set (struct peer *, afi_t, safi_t, int, char *);
+int peer_distribute_unset (struct peer *, afi_t, safi_t, int);
+
+int peer_allowas_in_set (struct peer *, afi_t, safi_t, int);
+int peer_allowas_in_unset (struct peer *, afi_t, safi_t);
+
+int peer_local_as_set (struct peer *, as_t, int);
+int peer_local_as_unset (struct peer *);
+
+int peer_prefix_list_set (struct peer *, afi_t, safi_t, int, char *);
+int peer_prefix_list_unset (struct peer *, afi_t, safi_t, int);
+
+int peer_aslist_set (struct peer *, afi_t, safi_t, int, char *);
+int peer_aslist_unset (struct peer *,afi_t, safi_t, int);
+
+int peer_route_map_set (struct peer *, afi_t, safi_t, int, char *);
+int peer_route_map_unset (struct peer *, afi_t, safi_t, int);
+
+int peer_unsuppress_map_set (struct peer *, afi_t, safi_t, char *);
+int peer_unsuppress_map_unset (struct peer *, afi_t, safi_t);
+
+int peer_maximum_prefix_set (struct peer *, afi_t, safi_t, u_int32_t, int);
+int peer_maximum_prefix_unset (struct peer *, afi_t, safi_t);
+
+int peer_clear (struct peer *);
+int peer_clear_soft (struct peer *, afi_t, safi_t, enum bgp_clear_type);