]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_packet.c
*: reindent
[mirror_frr.git] / bgpd / bgp_packet.c
index 2b48b34e13254bfa08908cb090cfd1973ff995ab..2860113d182f7ecde9d2d70513c1031d7d7ffc6a 100644 (file)
@@ -27,7 +27,7 @@
 #include "command.h"
 #include "log.h"
 #include "memory.h"
-#include "sockunion.h"         /* for inet_ntop () */
+#include "sockunion.h" /* for inet_ntop () */
 #include "sockopt.h"
 #include "linklist.h"
 #include "plist.h"
 #include "bgpd/bgp_label.h"
 
 /* Set up BGP packet marker and packet type. */
-int
-bgp_packet_set_marker (struct stream *s, u_char type)
+int bgp_packet_set_marker(struct stream *s, u_char type)
 {
-  int i;
+       int i;
 
-  /* Fill in marker. */
-  for (i = 0; i < BGP_MARKER_SIZE; i++)
-    stream_putc (s, 0xff);
+       /* 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);
+       /* Dummy total length. This field is should be filled in later on. */
+       stream_putw(s, 0);
 
-  /* BGP packet type. */
-  stream_putc (s, type);
+       /* BGP packet type. */
+       stream_putc(s, type);
 
-  /* Return current stream size. */
-  return stream_get_endp (s);
+       /* Return current stream size. */
+       return stream_get_endp(s);
 }
 
 /* Set BGP packet header size entry.  If size is zero then use current
    stream size. */
-int
-bgp_packet_set_size (struct stream *s)
+int bgp_packet_set_size(struct stream *s)
 {
-  int cp;
+       int cp;
 
-  /* Preserve current pointer. */
-  cp = stream_get_endp (s);
-  stream_putw_at (s, BGP_MARKER_SIZE, cp);
+       /* Preserve current pointer. */
+       cp = stream_get_endp(s);
+       stream_putw_at(s, BGP_MARKER_SIZE, cp);
 
-  return cp;
+       return cp;
 }
 
 /* Add new packet to the peer. */
-void
-bgp_packet_add (struct peer *peer, struct stream *s)
+void bgp_packet_add(struct peer *peer, struct stream *s)
 {
-  /* Add packet to the end of list. */
-  stream_fifo_push (peer->obuf, s);
+       /* Add packet to the end of list. */
+       stream_fifo_push(peer->obuf, s);
 }
 
 /* Free first packet. */
-static void
-bgp_packet_delete (struct peer *peer)
+static void bgp_packet_delete(struct peer *peer)
 {
-  stream_free (stream_fifo_pop (peer->obuf));
+       stream_free(stream_fifo_pop(peer->obuf));
 }
 
 /* Check file descriptor whether connect is established. */
-int
-bgp_connect_check (struct peer *peer, int change_state)
+int bgp_connect_check(struct peer *peer, int change_state)
 {
-  int status;
-  socklen_t 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_info ("can't get sockopt for nonblocking connect");
-      BGP_EVENT_ADD (peer, TCP_fatal_error);
-      return -1;
-    }      
-
-  /* When status is 0 then TCP connection is established. */
-  if (status == 0)
-    {
-      BGP_EVENT_ADD (peer, TCP_connection_open);
-      return 1;
-    }
-  else
-    {
-      if (bgp_debug_neighbor_events(peer))
-         zlog_debug ("%s [Event] Connect failed (%s)",
-                     peer->host, safe_strerror (errno));
-      if (change_state)
-       BGP_EVENT_ADD (peer, TCP_connection_open_failed);
-      return 0;
-    }
+       int status;
+       socklen_t 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_info("can't get sockopt for nonblocking connect");
+               BGP_EVENT_ADD(peer, TCP_fatal_error);
+               return -1;
+       }
+
+       /* When status is 0 then TCP connection is established. */
+       if (status == 0) {
+               BGP_EVENT_ADD(peer, TCP_connection_open);
+               return 1;
+       } else {
+               if (bgp_debug_neighbor_events(peer))
+                       zlog_debug("%s [Event] Connect failed (%s)", peer->host,
+                                  safe_strerror(errno));
+               if (change_state)
+                       BGP_EVENT_ADD(peer, TCP_connection_open_failed);
+               return 0;
+       }
 }
 
-static struct stream *
-bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi)
+static struct stream *bgp_update_packet_eor(struct peer *peer, afi_t afi,
+                                           safi_t safi)
 {
-  struct stream *s;
-  iana_afi_t pkt_afi;
-  safi_t pkt_safi;
-
-  if (DISABLE_BGP_ANNOUNCE)
-    return NULL;
-
-  if (bgp_debug_neighbor_events(peer))
-    zlog_debug ("send End-of-RIB for %s to %s", afi_safi_print (afi, safi), peer->host);
-
-  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);
-
-  if (afi == AFI_IP && safi == SAFI_UNICAST)
-    {
-      /* Total Path Attribute Length */
-      stream_putw (s, 0);
-    }
-  else
-    {
-      /* Convert AFI, SAFI to values for packet. */
-      bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi);
-
-      /* Total Path Attribute Length */
-      stream_putw (s, 6);
-      stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
-      stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
-      stream_putc (s, 3);
-      stream_putw (s, pkt_afi);
-      stream_putc (s, pkt_safi);
-    }
-
-  bgp_packet_set_size (s);
-  bgp_packet_add (peer, s);
-  return s;
+       struct stream *s;
+       iana_afi_t pkt_afi;
+       safi_t pkt_safi;
+
+       if (DISABLE_BGP_ANNOUNCE)
+               return NULL;
+
+       if (bgp_debug_neighbor_events(peer))
+               zlog_debug("send End-of-RIB for %s to %s",
+                          afi_safi_print(afi, safi), peer->host);
+
+       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);
+
+       if (afi == AFI_IP && safi == SAFI_UNICAST) {
+               /* Total Path Attribute Length */
+               stream_putw(s, 0);
+       } else {
+               /* Convert AFI, SAFI to values for packet. */
+               bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
+
+               /* Total Path Attribute Length */
+               stream_putw(s, 6);
+               stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
+               stream_putc(s, BGP_ATTR_MP_UNREACH_NLRI);
+               stream_putc(s, 3);
+               stream_putw(s, pkt_afi);
+               stream_putc(s, pkt_safi);
+       }
+
+       bgp_packet_set_size(s);
+       bgp_packet_add(peer, s);
+       return s;
 }
 
 /* Get next packet to be written.  */
-static struct stream *
-bgp_write_packet (struct peer *peer)
+static struct stream *bgp_write_packet(struct peer *peer)
 {
-  struct stream *s = NULL;
-  struct peer_af *paf;
-  struct bpacket *next_pkt;
-  afi_t afi;
-  safi_t safi;
-
-  s = stream_fifo_head (peer->obuf);
-  if (s)
-    return s;
-
-  /*
-   * The code beyond this part deals with update packets, proceed only
-   * if peer is Established and updates are not on hold (as part of
-   * update-delay post processing).
-   */
-  if (peer->status != Established)
-    return NULL;
-
-  if (peer->bgp && peer->bgp->main_peers_update_hold)
-    return NULL;
-
-  for (afi = AFI_IP; afi < AFI_MAX; afi++)
-    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
-      {
-        paf = peer_af_find (peer, afi, safi);
-        if (!paf || !PAF_SUBGRP(paf))
-          continue;
-        next_pkt = paf->next_pkt_to_send;
-
-       /* Try to generate a packet for the peer if we are at the end of
-        * the list. Always try to push out WITHDRAWs first. */
-        if (!next_pkt || !next_pkt->buffer)
-         {
-           next_pkt = subgroup_withdraw_packet(PAF_SUBGRP(paf));
-            if (!next_pkt || !next_pkt->buffer)
-             subgroup_update_packet (PAF_SUBGRP(paf));
-           next_pkt = paf->next_pkt_to_send;
-         }
-
-       /* If we still don't have a packet to send to the peer, then
-        * try to find out out if we have to send eor or if not, skip to
-        * the next AFI, SAFI.
-        * Don't send the EOR prematurely... if the subgroup's coalesce
-        * timer is running, the adjacency-out structure is not created
-        * yet.
+       struct stream *s = NULL;
+       struct peer_af *paf;
+       struct bpacket *next_pkt;
+       afi_t afi;
+       safi_t safi;
+
+       s = stream_fifo_head(peer->obuf);
+       if (s)
+               return s;
+
+       /*
+        * The code beyond this part deals with update packets, proceed only
+        * if peer is Established and updates are not on hold (as part of
+        * update-delay post processing).
         */
-        if (!next_pkt || !next_pkt->buffer)
-          {
-           if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV))
-             {
-               if (!(PAF_SUBGRP(paf))->t_coalesce &&
-                   peer->afc_nego[afi][safi] && peer->synctime
-                   && ! CHECK_FLAG (peer->af_sflags[afi][safi],
-                                    PEER_STATUS_EOR_SEND))
-                 {
-                   SET_FLAG (peer->af_sflags[afi][safi],
-                             PEER_STATUS_EOR_SEND);
-                   return bgp_update_packet_eor (peer, afi, safi);
-                 }
-             }
-           continue;
-         }
-
-
-        /*
-        * Found a packet template to send, overwrite packet with appropriate
-         * attributes from peer and advance peer
-        */
-        s = bpacket_reformat_for_peer (next_pkt, paf);
-        bpacket_queue_advance_peer (paf);
-        return s;
-      }
+       if (peer->status != Established)
+               return NULL;
+
+       if (peer->bgp && peer->bgp->main_peers_update_hold)
+               return NULL;
+
+       for (afi = AFI_IP; afi < AFI_MAX; afi++)
+               for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
+                       paf = peer_af_find(peer, afi, safi);
+                       if (!paf || !PAF_SUBGRP(paf))
+                               continue;
+                       next_pkt = paf->next_pkt_to_send;
+
+                       /* Try to generate a packet for the peer if we are at
+                        * the end of
+                        * the list. Always try to push out WITHDRAWs first. */
+                       if (!next_pkt || !next_pkt->buffer) {
+                               next_pkt = subgroup_withdraw_packet(
+                                       PAF_SUBGRP(paf));
+                               if (!next_pkt || !next_pkt->buffer)
+                                       subgroup_update_packet(PAF_SUBGRP(paf));
+                               next_pkt = paf->next_pkt_to_send;
+                       }
+
+                       /* If we still don't have a packet to send to the peer,
+                        * then
+                        * try to find out out if we have to send eor or if not,
+                        * skip to
+                        * the next AFI, SAFI.
+                        * Don't send the EOR prematurely... if the subgroup's
+                        * coalesce
+                        * timer is running, the adjacency-out structure is not
+                        * created
+                        * yet.
+                        */
+                       if (!next_pkt || !next_pkt->buffer) {
+                               if (CHECK_FLAG(peer->cap,
+                                              PEER_CAP_RESTART_RCV)) {
+                                       if (!(PAF_SUBGRP(paf))->t_coalesce
+                                           && peer->afc_nego[afi][safi]
+                                           && peer->synctime
+                                           && !CHECK_FLAG(
+                                                      peer->af_sflags[afi]
+                                                                     [safi],
+                                                      PEER_STATUS_EOR_SEND)) {
+                                               SET_FLAG(peer->af_sflags[afi]
+                                                                       [safi],
+                                                        PEER_STATUS_EOR_SEND);
+                                               return bgp_update_packet_eor(
+                                                       peer, afi, safi);
+                                       }
+                               }
+                               continue;
+                       }
+
+
+                       /*
+                        * Found a packet template to send, overwrite packet
+                        * with appropriate
+                        * attributes from peer and advance peer
+                        */
+                       s = bpacket_reformat_for_peer(next_pkt, paf);
+                       bpacket_queue_advance_peer(paf);
+                       return s;
+               }
 
-  return NULL;
+       return NULL;
 }
 
 /* The next action for the peer from a write perspective */
-static void
-bgp_write_proceed_actions (struct peer *peer)
+static void bgp_write_proceed_actions(struct peer *peer)
 {
-  afi_t afi;
-  safi_t safi;
-  struct peer_af *paf;
-  struct bpacket *next_pkt;
-  int fullq_found = 0;
-  struct update_subgroup *subgrp;
-
-  if (stream_fifo_head (peer->obuf))
-    {
-      BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
-      return;
-    }
-
-   for (afi = AFI_IP; afi < AFI_MAX; afi++)
-     for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
-      {
-        paf = peer_af_find (peer, afi, safi);
-        if (!paf)
-          continue;
-        subgrp = paf->subgroup;
-        if (!subgrp)
-          continue;
-
-        next_pkt = paf->next_pkt_to_send;
-        if (next_pkt && next_pkt->buffer)
-          {
-            BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
-            return;
-          }
-
-        /* No packets readily available for AFI/SAFI, are there subgroup packets
-         * that need to be generated? */
-        if (bpacket_queue_is_full(SUBGRP_INST(subgrp),
-                                  SUBGRP_PKTQ(subgrp)))
-          fullq_found = 1;
-        else if (subgroup_packets_to_build (subgrp))
-          {
-            BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
-            return;
-          }
-
-        /* No packets to send, see if EOR is pending */
-        if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV))
-          {
-            if (!subgrp->t_coalesce &&
-                peer->afc_nego[afi][safi] &&
-                peer->synctime &&
-                !CHECK_FLAG(peer->af_sflags[afi][safi],
-                            PEER_STATUS_EOR_SEND) &&
-                safi != SAFI_MPLS_VPN)
-              {
-                BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
-                return;
-              }
-
-          }
-      }
-  if (fullq_found)
-    {
-      BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
-      return;
-    }
+       afi_t afi;
+       safi_t safi;
+       struct peer_af *paf;
+       struct bpacket *next_pkt;
+       int fullq_found = 0;
+       struct update_subgroup *subgrp;
+
+       if (stream_fifo_head(peer->obuf)) {
+               BGP_WRITE_ON(peer->t_write, bgp_write, peer->fd);
+               return;
+       }
+
+       for (afi = AFI_IP; afi < AFI_MAX; afi++)
+               for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
+                       paf = peer_af_find(peer, afi, safi);
+                       if (!paf)
+                               continue;
+                       subgrp = paf->subgroup;
+                       if (!subgrp)
+                               continue;
+
+                       next_pkt = paf->next_pkt_to_send;
+                       if (next_pkt && next_pkt->buffer) {
+                               BGP_WRITE_ON(peer->t_write, bgp_write,
+                                            peer->fd);
+                               return;
+                       }
+
+                       /* No packets readily available for AFI/SAFI, are there
+                        * subgroup packets
+                        * that need to be generated? */
+                       if (bpacket_queue_is_full(SUBGRP_INST(subgrp),
+                                                 SUBGRP_PKTQ(subgrp)))
+                               fullq_found = 1;
+                       else if (subgroup_packets_to_build(subgrp)) {
+                               BGP_WRITE_ON(peer->t_write, bgp_write,
+                                            peer->fd);
+                               return;
+                       }
+
+                       /* No packets to send, see if EOR is pending */
+                       if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV)) {
+                               if (!subgrp->t_coalesce
+                                   && peer->afc_nego[afi][safi]
+                                   && peer->synctime
+                                   && !CHECK_FLAG(peer->af_sflags[afi][safi],
+                                                  PEER_STATUS_EOR_SEND)
+                                   && safi != SAFI_MPLS_VPN) {
+                                       BGP_WRITE_ON(peer->t_write, bgp_write,
+                                                    peer->fd);
+                                       return;
+                               }
+                       }
+               }
+       if (fullq_found) {
+               BGP_WRITE_ON(peer->t_write, bgp_write, peer->fd);
+               return;
+       }
 }
 
 /* Write packet to the peer. */
-int
-bgp_write (struct thread *thread)
+int bgp_write(struct thread *thread)
 {
-  struct peer *peer;
-  u_char type;
-  struct stream *s;
-  int num;
-  int update_last_write = 0;
-  unsigned int count = 0;
-  unsigned int oc = 0;
-
-  /* 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, 1);
-      return 0;
-    }
-
-  s = bgp_write_packet (peer);
-  if (!s)
-    {
-      bgp_write_proceed_actions (peer);
-      return 0;
-    }
-
-  sockopt_cork (peer->fd, 1);
-
-  oc = peer->update_out;
-
-  /* Nonblocking write until TCP output buffer is full.  */
-  do
-    {
-      int writenum;
-
-      /* 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);
-      if (num < 0)
-       {
-         /* write failed either retry needed or error */
-         if (ERRNO_IO_RETRY(errno))
-               break;
-
-          BGP_EVENT_ADD (peer, TCP_fatal_error);
-         return 0;
+       struct peer *peer;
+       u_char type;
+       struct stream *s;
+       int num;
+       int update_last_write = 0;
+       unsigned int count = 0;
+       unsigned int oc = 0;
+
+       /* 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, 1);
+               return 0;
        }
 
-      if (num != writenum)
-       {
-         /* Partial write */
-         stream_forward_getp (s, num);
-         break;
+       s = bgp_write_packet(peer);
+       if (!s) {
+               bgp_write_proceed_actions(peer);
+               return 0;
        }
 
-      /* Retrieve BGP packet type. */
-      stream_set_getp (s, BGP_MARKER_SIZE + 2);
-      type = stream_getc (s);
+       sockopt_cork(peer->fd, 1);
 
-      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;
+       oc = peer->update_out;
 
-         /* Overflow check. */
-         if (peer->v_start >= (60 * 2))
-           peer->v_start = (60 * 2);
+       /* Nonblocking write until TCP output buffer is full.  */
+       do {
+               int writenum;
 
-         /* Flush any existing events */
-         BGP_EVENT_ADD (peer, BGP_Stop);
-         goto done;
-
-       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;
-       }
+               /* Number of bytes to be sent.  */
+               writenum = stream_get_endp(s) - stream_get_getp(s);
 
-      /* OK we send packet so delete it. */
-      bgp_packet_delete (peer);
-      update_last_write = 1;
-    }
-  while (++count < peer->bgp->wpkt_quanta &&
-        (s = bgp_write_packet (peer)) != NULL);
+               /* Call write() system call.  */
+               num = write(peer->fd, STREAM_PNT(s), writenum);
+               if (num < 0) {
+                       /* write failed either retry needed or error */
+                       if (ERRNO_IO_RETRY(errno))
+                               break;
 
-  bgp_write_proceed_actions (peer);
+                       BGP_EVENT_ADD(peer, TCP_fatal_error);
+                       return 0;
+               }
 
- done:
-  /* Update last_update if UPDATEs were written. */
-  if (peer->update_out > oc)
-    peer->last_update = bgp_clock ();
+               if (num != writenum) {
+                       /* Partial write */
+                       stream_forward_getp(s, num);
+                       break;
+               }
 
-  /* If we TXed any flavor of packet update last_write */
-  if (update_last_write)
-    peer->last_write = bgp_clock ();
+               /* 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);
+
+                       /* Flush any existing events */
+                       BGP_EVENT_ADD(peer, BGP_Stop);
+                       goto done;
+
+               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;
+               }
 
-  sockopt_cork (peer->fd, 0);
-  return 0;
-}
+               /* OK we send packet so delete it. */
+               bgp_packet_delete(peer);
+               update_last_write = 1;
+       } while (++count < peer->bgp->wpkt_quanta
+                && (s = bgp_write_packet(peer)) != NULL);
 
-/* This is only for sending NOTIFICATION message to neighbor. */
-static int
-bgp_write_notify (struct peer *peer)
-{
-  int ret, val;
-  u_char type;
-  struct stream *s;
+       bgp_write_proceed_actions(peer);
 
-  /* 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);
+done:
+       /* Update last_update if UPDATEs were written. */
+       if (peer->update_out > oc)
+               peer->last_update = bgp_clock();
 
-  /* Stop collecting data within the socket */
-  sockopt_cork (peer->fd, 0);
+       /* If we TXed any flavor of packet update last_write */
+       if (update_last_write)
+               peer->last_write = bgp_clock();
 
-  /* socket is in nonblocking mode, if we can't deliver the NOTIFY, well,
-   * we only care about getting a clean shutdown at this point. */
-  ret = write (peer->fd, STREAM_DATA (s), stream_get_endp (s));
+       sockopt_cork(peer->fd, 0);
+       return 0;
+}
 
-  /* only connection reset/close gets counted as TCP_fatal_error, failure
-   * to write the entire NOTIFY doesn't get different FSM treatment */
-  if (ret <= 0)
-    {
-      BGP_EVENT_ADD (peer, TCP_fatal_error);
-      return 0;
-    }
+/* This is only for sending NOTIFICATION message to neighbor. */
+static int bgp_write_notify(struct peer *peer)
+{
+       int ret, val;
+       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);
+
+       /* Stop collecting data within the socket */
+       sockopt_cork(peer->fd, 0);
+
+       /* socket is in nonblocking mode, if we can't deliver the NOTIFY, well,
+        * we only care about getting a clean shutdown at this point. */
+       ret = write(peer->fd, STREAM_DATA(s), stream_get_endp(s));
+
+       /* only connection reset/close gets counted as TCP_fatal_error, failure
+        * to write the entire NOTIFY doesn't get different FSM treatment */
+       if (ret <= 0) {
+               BGP_EVENT_ADD(peer, TCP_fatal_error);
+               return 0;
+       }
 
-  /* Disable Nagle, make NOTIFY packet go out right away */
-  val = 1;
-  (void) setsockopt (peer->fd, IPPROTO_TCP, TCP_NODELAY,
-                            (char *) &val, sizeof (val));
+       /* Disable Nagle, make NOTIFY packet go out right away */
+       val = 1;
+       (void)setsockopt(peer->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val,
+                        sizeof(val));
 
-  /* Retrieve BGP packet type. */
-  stream_set_getp (s, BGP_MARKER_SIZE + 2);
-  type = stream_getc (s);
+       /* Retrieve BGP packet type. */
+       stream_set_getp(s, BGP_MARKER_SIZE + 2);
+       type = stream_getc(s);
 
-  assert (type == BGP_MSG_NOTIFY);
+       assert(type == BGP_MSG_NOTIFY);
 
-  /* Type should be notify. */
-  peer->notify_out++;
+       /* Type should be notify. */
+       peer->notify_out++;
 
-  /* Double start timer. */
-  peer->v_start *= 2;
+       /* Double start timer. */
+       peer->v_start *= 2;
 
-  /* Overflow check. */
-  if (peer->v_start >= (60 * 2))
-    peer->v_start = (60 * 2);
+       /* Overflow check. */
+       if (peer->v_start >= (60 * 2))
+               peer->v_start = (60 * 2);
 
-  /* Handle Graceful Restart case where the state changes to
-     Connect instead of Idle */
-  BGP_EVENT_ADD (peer, BGP_Stop);
+       /* Handle Graceful Restart case where the state changes to
+          Connect instead of Idle */
+       BGP_EVENT_ADD(peer, BGP_Stop);
 
-  return 0;
+       return 0;
 }
 
 /* Make keepalive packet and send it to the peer. */
-void
-bgp_keepalive_send (struct peer *peer)
+void bgp_keepalive_send(struct peer *peer)
 {
-  struct stream *s;
+       struct stream *s;
+
+       s = stream_new(BGP_MAX_PACKET_SIZE);
 
-  s = stream_new (BGP_MAX_PACKET_SIZE);
+       /* Make keepalive packet. */
+       bgp_packet_set_marker(s, BGP_MSG_KEEPALIVE);
 
-  /* Make keepalive packet. */
-  bgp_packet_set_marker (s, BGP_MSG_KEEPALIVE);
+       /* Set packet size. */
+       (void)bgp_packet_set_size(s);
 
-  /* Set packet size. */
-  (void)bgp_packet_set_size (s);
+       /* Dump packet if debug option is set. */
+       /* bgp_packet_dump (s); */
 
-  /* Dump packet if debug option is set. */
-  /* bgp_packet_dump (s); */
-  if (bgp_debug_keepalive(peer))
-    zlog_debug ("%s sending KEEPALIVE", peer->host); 
+       if (bgp_debug_keepalive(peer))
+               zlog_debug("%s sending KEEPALIVE", peer->host);
 
-  /* Add packet to the peer. */
-  bgp_packet_add (peer, s);
+       /* Add packet to the peer. */
+       bgp_packet_add(peer, s);
 
-  BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+       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)
+void bgp_open_send(struct peer *peer)
 {
-  struct stream *s;
-  u_int16_t send_holdtime;
-  as_t local_as;
+       struct stream *s;
+       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;
+       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; 
+       /* 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);
+       s = stream_new(BGP_MAX_PACKET_SIZE);
 
-  /* Make open packet. */
-  bgp_packet_set_marker (s, BGP_MSG_OPEN);
+       /* 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 <= BGP_AS_MAX) ? (u_int16_t) local_as 
-                                           : BGP_AS_TRANS);
-  stream_putw (s, send_holdtime);       /* Hold Time */
-  stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */
+       /* Set open packet values. */
+       stream_putc(s, BGP_VERSION_4); /* BGP version */
+       stream_putw(s,
+                   (local_as <= BGP_AS_MAX) ? (u_int16_t)local_as
+                                            : BGP_AS_TRANS);
+       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 capability code. */
+       bgp_open_capability(s, peer);
 
-  /* Set BGP packet length. */
-  (void)bgp_packet_set_size (s);
+       /* Set BGP packet length. */
+       (void)bgp_packet_set_size(s);
 
-  if (bgp_debug_neighbor_events(peer))
-    zlog_debug ("%s sending OPEN, version %d, my as %u, holdtime %d, id %s", 
-              peer->host, BGP_VERSION_4, local_as,
-              send_holdtime, inet_ntoa (peer->local_id));
+       if (bgp_debug_neighbor_events(peer))
+               zlog_debug(
+                       "%s sending OPEN, version %d, my as %u, holdtime %d, id %s",
+                       peer->host, BGP_VERSION_4, local_as, send_holdtime,
+                       inet_ntoa(peer->local_id));
 
-  /* Dump packet if debug option is set. */
-  /* bgp_packet_dump (s); */
+       /* Dump packet if debug option is set. */
+       /* bgp_packet_dump (s); */
 
-  /* Add packet to the peer. */
-  bgp_packet_add (peer, s);
+       /* Add packet to the peer. */
+       bgp_packet_add(peer, s);
 
-  BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+       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)
+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;
-    bgp_notify.raw_data = data;
-
-    peer->notify.code = bgp_notify.code;
-    peer->notify.subcode = bgp_notify.subcode;
-    
-    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);
-        bgp_notify.data = NULL;
-        bgp_notify.length = 0;
-      }
-  }
-
-  /* peer reset cause */
-  if (code == BGP_NOTIFY_CEASE)
-    {
-      if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET)
-        peer->last_reset = PEER_DOWN_USER_RESET;
-      else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN)
-        peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
-      else
-        peer->last_reset = PEER_DOWN_NOTIFY_SEND;
-    }
-  else
-    peer->last_reset = PEER_DOWN_NOTIFY_SEND;
-
-  /* Call immediately. */
-  BGP_WRITE_OFF (peer->t_write);
-
-  bgp_write_notify (peer);
+       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;
+               bgp_notify.raw_data = data;
+
+               peer->notify.code = bgp_notify.code;
+               peer->notify.subcode = bgp_notify.subcode;
+
+               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);
+                       bgp_notify.data = NULL;
+                       bgp_notify.length = 0;
+               }
+       }
+
+       /* peer reset cause */
+       if (code == BGP_NOTIFY_CEASE) {
+               if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET)
+                       peer->last_reset = PEER_DOWN_USER_RESET;
+               else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN)
+                       peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
+               else
+                       peer->last_reset = PEER_DOWN_NOTIFY_SEND;
+       } else
+               peer->last_reset = PEER_DOWN_NOTIFY_SEND;
+
+       /* Call immediately. */
+       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)
+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);
+       bgp_notify_send_with_data(peer, code, sub_code, NULL, 0);
 }
 
 /* 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)
+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 bgp_filter *filter;
-  int orf_refresh = 0;
-  iana_afi_t pkt_afi;
-  safi_t pkt_safi;
-
-  if (DISABLE_BGP_ANNOUNCE)
-    return;
-
-  filter = &peer->filter[afi][safi];
-
-  /* Convert AFI, SAFI to values for packet. */
-  bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi);
-  
-  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, pkt_afi);
-  stream_putc (s, 0);
-  stream_putc (s, pkt_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_endp (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_neighbor_events(peer))
-             zlog_debug ("%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"),
-                        pkt_afi, pkt_safi);
-         }
+       struct stream *s;
+       struct bgp_filter *filter;
+       int orf_refresh = 0;
+       iana_afi_t pkt_afi;
+       safi_t pkt_safi;
+
+       if (DISABLE_BGP_ANNOUNCE)
+               return;
+
+       filter = &peer->filter[afi][safi];
+
+       /* Convert AFI, SAFI to values for packet. */
+       bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
+
+       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
-         {
-           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_neighbor_events(peer))
-             zlog_debug ("%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"),
-                        pkt_afi, pkt_safi);
-         }
-
-       /* Total ORF Entry Len. */
-       orf_len = stream_get_endp (s) - orfp - 2;
-       stream_putw_at (s, orfp, orf_len);
-      }
-
-  /* Set packet size. */
-  (void)bgp_packet_set_size (s);
-
-  if (bgp_debug_neighbor_events(peer))
-    {
-      if (! orf_refresh)
-       zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d", 
-                  peer->host, pkt_afi, pkt_safi);
-    }
-
-  /* Add packet to the peer. */
-  bgp_packet_add (peer, s);
-
-  BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
+               bgp_packet_set_marker(s, BGP_MSG_ROUTE_REFRESH_OLD);
+
+       /* Encode Route Refresh message. */
+       stream_putw(s, pkt_afi);
+       stream_putc(s, 0);
+       stream_putc(s, pkt_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_endp(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_neighbor_events(peer))
+                                       zlog_debug(
+                                               "%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"),
+                                               pkt_afi, pkt_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_neighbor_events(peer))
+                                       zlog_debug(
+                                               "%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"),
+                                               pkt_afi, pkt_safi);
+                       }
+
+                       /* Total ORF Entry Len. */
+                       orf_len = stream_get_endp(s) - orfp - 2;
+                       stream_putw_at(s, orfp, orf_len);
+               }
+
+       /* Set packet size. */
+       (void)bgp_packet_set_size(s);
+
+       if (bgp_debug_neighbor_events(peer)) {
+               if (!orf_refresh)
+                       zlog_debug("%s sending REFRESH_REQ for afi/safi: %d/%d",
+                                  peer->host, pkt_afi, pkt_safi);
+       }
+
+       /* Add packet to the peer. */
+       bgp_packet_add(peer, s);
+
+       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)
+void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
+                        int capability_code, int action)
 {
-  struct stream *s;
-  iana_afi_t pkt_afi;
-  safi_t pkt_safi;
+       struct stream *s;
+       iana_afi_t pkt_afi;
+       safi_t pkt_safi;
+
+       /* Convert AFI, SAFI to values for packet. */
+       bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
+
+       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, pkt_afi);
+               stream_putc(s, 0);
+               stream_putc(s, pkt_safi);
+
+               if (bgp_debug_neighbor_events(peer))
+                       zlog_debug(
+                               "%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d",
+                               peer->host,
+                               action == CAPABILITY_ACTION_SET ? "Advertising"
+                                                               : "Removing",
+                               pkt_afi, pkt_safi);
+       }
+
+       /* Set packet size. */
+       (void)bgp_packet_set_size(s);
 
-  /* Convert AFI, SAFI to values for packet. */
-  bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi);
+       /* Add packet to the peer. */
+       bgp_packet_add(peer, s);
 
-  s = stream_new (BGP_MAX_PACKET_SIZE);
+       BGP_WRITE_ON(peer->t_write, bgp_write, peer->fd);
+}
 
-  /* Make BGP update packet. */
-  bgp_packet_set_marker (s, BGP_MSG_CAPABILITY);
+/* RFC1771 6.8 Connection collision detection. */
+static int bgp_collision_detect(struct peer *new, struct in_addr remote_id)
+{
+       struct peer *peer;
+
+       /* 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: */
+
+       if ((peer = new->doppelganger) != NULL) {
+               /* Do not accept the new connection in Established or Clearing
+                * states.
+                * Note that a peer GR is handled by closing the existing
+                * connection
+                * upon receipt of new one.
+                */
+               if (peer->status == Established || peer->status == Clearing) {
+                       bgp_notify_send(new, BGP_NOTIFY_CEASE,
+                                       BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
+                       return (-1);
+               } else if ((peer->status == OpenConfirm)
+                          || (peer->status == OpenSent)) {
+                       /* 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))
+                               if (!CHECK_FLAG(peer->sflags,
+                                               PEER_STATUS_ACCEPT_PEER)) {
+                                       /* 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. */
+                                       bgp_notify_send(
+                                               peer, BGP_NOTIFY_CEASE,
+                                               BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
+                                       return 1;
+                               } else {
+                                       bgp_notify_send(
+                                               new, BGP_NOTIFY_CEASE,
+                                               BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
+                                       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 (CHECK_FLAG(peer->sflags,
+                                              PEER_STATUS_ACCEPT_PEER)) {
+                                       bgp_notify_send(
+                                               peer, BGP_NOTIFY_CEASE,
+                                               BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
+                                       return 1;
+                               } else {
+                                       bgp_notify_send(
+                                               new, BGP_NOTIFY_CEASE,
+                                               BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
+                                       return -1;
+                               }
+                       }
+               }
+       }
+       return 0;
+}
 
-  /* 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, pkt_afi);
-      stream_putc (s, 0);
-      stream_putc (s, pkt_safi);
+static 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;
+       as_t as4 = 0;
+       struct in_addr remote_id;
+       int mp_capability;
+       u_int8_t notify_data_remote_as[2];
+       u_int8_t notify_data_remote_as4[4];
+       u_int8_t notify_data_remote_id[4];
+       u_int16_t *holdtime_ptr;
+
+       /* 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_ptr = (u_int16_t *)stream_pnt(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_neighbor_events(peer))
+               zlog_debug(
+                       "%s rcv OPEN, version %d, remote-as (in open) %u,"
+                       " holdtime %d, id %s",
+                       peer->host, version, remote_as, holdtime,
+                       inet_ntoa(remote_id));
+
+       /* BEGIN to read the capability here, but dont do it yet */
+       mp_capability = 0;
+       optlen = stream_getc(peer->ibuf);
+
+       if (optlen != 0) {
+               /* If not enough bytes, it is an error. */
+               if (STREAM_READABLE(peer->ibuf) < optlen) {
+                       bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
+                                       BGP_NOTIFY_OPEN_MALFORMED_ATTR);
+                       return -1;
+               }
 
-      if (bgp_debug_neighbor_events(peer))
-        zlog_debug ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d",
-                  peer->host, action == CAPABILITY_ACTION_SET ?
-                  "Advertising" : "Removing", pkt_afi, pkt_safi);
-    }
+               /* We need the as4 capability value *right now* because
+                * if it is there, we have not got the remote_as yet, and
+                * without
+                * that we do not know which peer is connecting to us now.
+                */
+               as4 = peek_for_as4_capability(peer, optlen);
+               memcpy(notify_data_remote_as4, &as4, 4);
+       }
 
-  /* Set packet size. */
-  (void)bgp_packet_set_size (s);
+       /* Just in case we have a silly peer who sends AS4 capability set to 0
+        */
+       if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV) && !as4) {
+               zlog_err("%s bad OPEN, got AS4 capability, but AS4 set to 0",
+                        peer->host);
+               bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,
+                                         BGP_NOTIFY_OPEN_BAD_PEER_AS,
+                                         notify_data_remote_as4, 4);
+               return -1;
+       }
 
-  /* Add packet to the peer. */
-  bgp_packet_add (peer, s);
+       if (remote_as == BGP_AS_TRANS) {
+               /* Take the AS4 from the capability.  We must have received the
+                * capability now!  Otherwise we have a asn16 peer who uses
+                * BGP_AS_TRANS, for some unknown reason.
+                */
+               if (as4 == BGP_AS_TRANS) {
+                       zlog_err(
+                               "%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed",
+                               peer->host);
+                       bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,
+                                                 BGP_NOTIFY_OPEN_BAD_PEER_AS,
+                                                 notify_data_remote_as4, 4);
+                       return -1;
+               }
 
-  BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
-}
+               if (!as4 && BGP_DEBUG(as4, AS4))
+                       zlog_debug(
+                               "%s [AS4] OPEN remote_as is AS_TRANS, but no AS4."
+                               " Odd, but proceeding.",
+                               peer->host);
+               else if (as4 < BGP_AS_MAX && BGP_DEBUG(as4, AS4))
+                       zlog_debug(
+                               "%s [AS4] OPEN remote_as is AS_TRANS, but AS4 (%u) fits "
+                               "in 2-bytes, very odd peer.",
+                               peer->host, as4);
+               if (as4)
+                       remote_as = as4;
+       } else {
+               /* We may have a partner with AS4 who has an asno < BGP_AS_MAX
+                */
+               /* If we have got the capability, peer->as4cap must match
+                * remote_as */
+               if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)
+                   && as4 != remote_as) {
+                       /* raise error, log this, close session */
+                       zlog_err(
+                               "%s bad OPEN, got AS4 capability, but remote_as %u"
+                               " mismatch with 16bit 'myasn' %u in open",
+                               peer->host, as4, remote_as);
+                       bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,
+                                                 BGP_NOTIFY_OPEN_BAD_PEER_AS,
+                                                 notify_data_remote_as4, 4);
+                       return -1;
+               }
+       }
 
-/* RFC1771 6.8 Connection collision detection. */
-static int
-bgp_collision_detect (struct peer *new, struct in_addr remote_id)
-{
-  struct peer *peer;
-
-  /* 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: */
-
-  if ((peer = new->doppelganger) != NULL)
-    {
-      /* Do not accept the new connection in Established or Clearing states.
-       * Note that a peer GR is handled by closing the existing connection
-       * upon receipt of new one.
-       */
-      if (peer->status == Established || peer->status == Clearing)
-        {
-          bgp_notify_send (new, BGP_NOTIFY_CEASE,
-                           BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
-          return (-1);
-        }
-      else if ((peer->status == OpenConfirm) || (peer->status == OpenSent))
-       {
-         /* 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))
-           if (!CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER))
-             {
-               /* 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. */
-               bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-                                BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
-               return 1;
-             }
-           else
-             {
-               bgp_notify_send (new, BGP_NOTIFY_CEASE,
-                                BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
+       /* remote router-id check. */
+       if (remote_id.s_addr == 0 || IPV4_CLASS_DE(ntohl(remote_id.s_addr))
+           || ntohl(peer->local_id.s_addr) == ntohl(remote_id.s_addr)) {
+               if (bgp_debug_neighbor_events(peer))
+                       zlog_debug("%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) {
+               u_int16_t maxver = htons(BGP_VERSION_4);
+               /* XXX this reply may not be correct if version < 4  XXX */
+               if (bgp_debug_neighbor_events(peer))
+                       zlog_debug(
+                               "%s bad protocol version, remote requested %d, local request %d",
+                               peer->host, version, BGP_VERSION_4);
+               /* Data must be in network byte order here */
+               bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,
+                                         BGP_NOTIFY_OPEN_UNSUP_VERSION,
+                                         (u_int8_t *)&maxver, 2);
+               return -1;
+       }
+
+       /* Check neighbor as number. */
+       if (peer->as_type == AS_UNSPECIFIED) {
+               if (bgp_debug_neighbor_events(peer))
+                       zlog_debug(
+                               "%s bad OPEN, remote AS is unspecified currently",
+                               peer->host);
+               bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,
+                                         BGP_NOTIFY_OPEN_BAD_PEER_AS,
+                                         notify_data_remote_as, 2);
                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 (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER))
-               {
-                 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-                                  BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
-                 return 1;
+       } else if (peer->as_type == AS_INTERNAL) {
+               if (remote_as != peer->bgp->as) {
+                       if (bgp_debug_neighbor_events(peer))
+                               zlog_debug(
+                                       "%s bad OPEN, remote AS is %u, internal specified",
+                                       peer->host, remote_as);
+                       bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,
+                                                 BGP_NOTIFY_OPEN_BAD_PEER_AS,
+                                                 notify_data_remote_as, 2);
+                       return -1;
                }
-             else
-               {
-                 bgp_notify_send (new, BGP_NOTIFY_CEASE,
-                                  BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
-                 return -1;
+               peer->as = peer->local_as;
+       } else if (peer->as_type == AS_EXTERNAL) {
+               if (remote_as == peer->bgp->as) {
+                       if (bgp_debug_neighbor_events(peer))
+                               zlog_debug(
+                                       "%s bad OPEN, remote AS is %u, external specified",
+                                       peer->host, remote_as);
+                       bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,
+                                                 BGP_NOTIFY_OPEN_BAD_PEER_AS,
+                                                 notify_data_remote_as, 2);
+                       return -1;
                }
-           }
+               peer->as = remote_as;
+       } else if ((peer->as_type == AS_SPECIFIED) && (remote_as != peer->as)) {
+               if (bgp_debug_neighbor_events(peer))
+                       zlog_debug("%s bad OPEN, remote AS is %u, expected %u",
+                                  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;
        }
-    }
-  return 0;
-}
 
-static 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;
-  as_t as4 = 0;
-  struct in_addr remote_id;
-  int mp_capability;
-  u_int8_t notify_data_remote_as[2];
-  u_int8_t notify_data_remote_as4[4];
-  u_int8_t notify_data_remote_id[4];
-  u_int16_t *holdtime_ptr;
-
-  /* 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_ptr = (u_int16_t *)stream_pnt (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_neighbor_events(peer))
-    zlog_debug ("%s rcv OPEN, version %d, remote-as (in open) %u,"
-                " holdtime %d, id %s",
-               peer->host, version, remote_as, holdtime,
-               inet_ntoa (remote_id));
-  
-  /* BEGIN to read the capability here, but dont do it yet */
-  mp_capability = 0;
-  optlen = stream_getc (peer->ibuf);
-  
-  if (optlen != 0)
-    {
-      /* If not enough bytes, it is an error. */
-      if (STREAM_READABLE(peer->ibuf) < optlen)
-        {
-          bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
-                           BGP_NOTIFY_OPEN_MALFORMED_ATTR);
-          return -1;
-        }
-
-      /* We need the as4 capability value *right now* because
-       * if it is there, we have not got the remote_as yet, and without
-       * that we do not know which peer is connecting to us now.
-       */ 
-      as4 = peek_for_as4_capability (peer, optlen);
-      memcpy (notify_data_remote_as4, &as4, 4);
-    }
-  
-  /* Just in case we have a silly peer who sends AS4 capability set to 0 */
-  if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) && !as4)
-    {
-      zlog_err ("%s bad OPEN, got AS4 capability, but AS4 set to 0",
-                peer->host);
-      bgp_notify_send_with_data (peer,
-                                 BGP_NOTIFY_OPEN_ERR,
-                                 BGP_NOTIFY_OPEN_BAD_PEER_AS,
-                                 notify_data_remote_as4, 4);
-      return -1;
-    }
-  
-  if (remote_as == BGP_AS_TRANS)
-    {
-         /* Take the AS4 from the capability.  We must have received the
-          * capability now!  Otherwise we have a asn16 peer who uses
-          * BGP_AS_TRANS, for some unknown reason.
+       /* 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 (as4 == BGP_AS_TRANS)
-        {
-          zlog_err ("%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed",
-                    peer->host);
-          bgp_notify_send_with_data (peer,
-                                     BGP_NOTIFY_OPEN_ERR,
-                                     BGP_NOTIFY_OPEN_BAD_PEER_AS,
-                                     notify_data_remote_as4, 4);
-          return -1;
-        }
-      
-      if (!as4 && BGP_DEBUG (as4, AS4))
-        zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but no AS4."
-                    " Odd, but proceeding.", peer->host);
-      else if (as4 < BGP_AS_MAX && BGP_DEBUG (as4, AS4))
-        zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but AS4 (%u) fits "
-                    "in 2-bytes, very odd peer.", peer->host, as4);
-      if (as4)
-        remote_as = as4;
-    } 
-  else 
-    {
-      /* We may have a partner with AS4 who has an asno < BGP_AS_MAX */
-      /* If we have got the capability, peer->as4cap must match remote_as */
-      if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)
-          && as4 != remote_as)
-        {
-         /* raise error, log this, close session */
-         zlog_err ("%s bad OPEN, got AS4 capability, but remote_as %u"
-                   " mismatch with 16bit 'myasn' %u in open",
-                   peer->host, as4, remote_as);
-          bgp_notify_send_with_data (peer,
-                                     BGP_NOTIFY_OPEN_ERR,
-                                     BGP_NOTIFY_OPEN_BAD_PEER_AS,
-                                     notify_data_remote_as4, 4);
-         return -1;
+
+       if (holdtime < 3 && holdtime != 0) {
+               bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,
+                                         BGP_NOTIFY_OPEN_UNACEP_HOLDTIME,
+                                         (u_char *)holdtime_ptr, 2);
+               return -1;
        }
-    }
-
-  /* remote router-id check. */
-  if (remote_id.s_addr == 0
-      || IPV4_CLASS_DE (ntohl (remote_id.s_addr))
-      || ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr))
-    {
-      if (bgp_debug_neighbor_events(peer))
-       zlog_debug ("%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)
-    {
-      u_int16_t maxver = htons(BGP_VERSION_4);
-      /* XXX this reply may not be correct if version < 4  XXX */
-      if (bgp_debug_neighbor_events(peer))
-       zlog_debug ("%s bad protocol version, remote requested %d, local request %d",
-                  peer->host, version, BGP_VERSION_4);
-      /* Data must be in network byte order here */
-      bgp_notify_send_with_data (peer, 
-                                BGP_NOTIFY_OPEN_ERR, 
-                                BGP_NOTIFY_OPEN_UNSUP_VERSION,
-                                (u_int8_t *) &maxver, 2);
-      return -1;
-    }
-
-  /* Check neighbor as number. */
-  if (peer->as_type == AS_UNSPECIFIED)
-    {
-      if (bgp_debug_neighbor_events(peer))
-       zlog_debug("%s bad OPEN, remote AS is unspecified currently", peer->host);
-      bgp_notify_send_with_data(peer,
-                               BGP_NOTIFY_OPEN_ERR,
-                               BGP_NOTIFY_OPEN_BAD_PEER_AS,
-                               notify_data_remote_as, 2);
-      return -1;
-    }
-  else if (peer->as_type == AS_INTERNAL)
-    {
-      if (remote_as != peer->bgp->as)
-       {
-         if (bgp_debug_neighbor_events(peer))
-           zlog_debug ("%s bad OPEN, remote AS is %u, internal specified",
-                       peer->host, remote_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: 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;
+
+       if (CHECK_FLAG(peer->config, PEER_CONFIG_TIMER))
+               peer->v_keepalive = peer->keepalive;
+       else
+               peer->v_keepalive = peer->v_holdtime / 3;
+
+       /* Open option part parse. */
+       if (optlen != 0) {
+               if ((ret = bgp_open_option_parse(peer, optlen, &mp_capability))
+                   < 0)
+                       return ret;
+       } else {
+               if (bgp_debug_neighbor_events(peer))
+                       zlog_debug("%s rcvd OPEN w/ OPTION parameter len: 0",
+                                  peer->host);
        }
-      peer->as = peer->local_as;
-    }
-  else if (peer->as_type == AS_EXTERNAL)
-    {
-      if (remote_as == peer->bgp->as)
-       {
-         if (bgp_debug_neighbor_events(peer))
-           zlog_debug ("%s bad OPEN, remote AS is %u, external specified",
-                       peer->host, remote_as);
-         bgp_notify_send_with_data (peer,
-                                    BGP_NOTIFY_OPEN_ERR,
-                                    BGP_NOTIFY_OPEN_BAD_PEER_AS,
-                                    notify_data_remote_as, 2);
-         return -1;
+
+       /*
+        * Assume that the peer supports the locally configured set of
+        * AFI/SAFIs if the peer did not send us any Mulitiprotocol
+        * capabilities, or if 'override-capability' is configured.
+        */
+       if (!mp_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_IP][SAFI_LABELED_UNICAST] =
+                       peer->afc[AFI_IP][SAFI_LABELED_UNICAST];
+               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];
+               peer->afc_nego[AFI_IP6][SAFI_LABELED_UNICAST] =
+                       peer->afc[AFI_IP6][SAFI_LABELED_UNICAST];
+               peer->afc_nego[AFI_L2VPN][SAFI_EVPN] =
+                       peer->afc[AFI_L2VPN][SAFI_EVPN];
        }
-      peer->as = remote_as;
-    }
-  else if ((peer->as_type == AS_SPECIFIED) && (remote_as != peer->as))
-    {
-      if (bgp_debug_neighbor_events(peer))
-       zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
-                   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_with_data (peer,
-                                BGP_NOTIFY_OPEN_ERR,
-                                BGP_NOTIFY_OPEN_UNACEP_HOLDTIME,
-                                 (u_char *)holdtime_ptr, 2);
-      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;
-
-  if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
-    peer->v_keepalive = peer->keepalive;
-  else
-    peer->v_keepalive = peer->v_holdtime / 3;
-
-  /* Open option part parse. */
-  if (optlen != 0) 
-    {
-      if ((ret = bgp_open_option_parse (peer, optlen, &mp_capability)) < 0)
-       return ret;
-    }
-  else
-    {
-      if (bgp_debug_neighbor_events(peer))
-       zlog_debug ("%s rcvd OPEN w/ OPTION parameter len: 0",
-                  peer->host);
-    }
-
-  /* 
-   * Assume that the peer supports the locally configured set of
-   * AFI/SAFIs if the peer did not send us any Mulitiprotocol
-   * capabilities, or if 'override-capability' is configured.
-   */
-  if (! mp_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_IP][SAFI_LABELED_UNICAST] = peer->afc[AFI_IP][SAFI_LABELED_UNICAST];
-      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];
-      peer->afc_nego[AFI_IP6][SAFI_LABELED_UNICAST] = peer->afc[AFI_IP6][SAFI_LABELED_UNICAST];
-      peer->afc_nego[AFI_L2VPN][SAFI_EVPN] = peer->afc[AFI_L2VPN][SAFI_EVPN];
-    }
-
-  /* When collision is detected and this peer is closed.  Retrun
-     immidiately. */
-  ret = bgp_collision_detect (peer, remote_id);
-  if (ret < 0)
-    return ret;
-
-  /* Get sockname. */
-  if ((ret = bgp_getsockname (peer)) < 0)
-    {
-      zlog_err("%s: bgp_getsockname() failed for peer: %s", __FUNCTION__,
-              peer->host);
-      return (ret);
-    }
-
-  /* Verify valid local address present based on negotiated address-families. */
-  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_IP][SAFI_ENCAP])
-    {
-      if (!peer->nexthop.v4.s_addr)
-        {
-#if defined (HAVE_CUMULUS)
-          zlog_err ("%s: No local IPv4 addr resetting connection, fd %d",
-                    peer->host, peer->fd);
-          bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_SUBCODE_UNSPECIFIC);
-          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;
+
+       /* Get sockname. */
+       if ((ret = bgp_getsockname(peer)) < 0) {
+               zlog_err("%s: bgp_getsockname() failed for peer: %s",
+                        __FUNCTION__, peer->host);
+               return (ret);
+       }
+
+       /* Verify valid local address present based on negotiated
+        * address-families. */
+       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_IP][SAFI_ENCAP]) {
+               if (!peer->nexthop.v4.s_addr) {
+#if defined(HAVE_CUMULUS)
+                       zlog_err(
+                               "%s: No local IPv4 addr resetting connection, fd %d",
+                               peer->host, peer->fd);
+                       bgp_notify_send(peer, BGP_NOTIFY_CEASE,
+                                       BGP_NOTIFY_SUBCODE_UNSPECIFIC);
+                       return -1;
 #endif
-        }
-    }
-  if (peer->afc_nego[AFI_IP6][SAFI_UNICAST] ||
-      peer->afc_nego[AFI_IP6][SAFI_MULTICAST] ||
-      peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN] ||
-      peer->afc_nego[AFI_IP6][SAFI_ENCAP])
-    {
-      if (IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_global))
-        {
-#if defined (HAVE_CUMULUS)
-          zlog_err ("%s: No local IPv6 addr resetting connection, fd %d",
-                    peer->host, peer->fd);
-          bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_SUBCODE_UNSPECIFIC);
-          return -1;
+               }
+       }
+       if (peer->afc_nego[AFI_IP6][SAFI_UNICAST]
+           || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
+           || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
+           || peer->afc_nego[AFI_IP6][SAFI_ENCAP]) {
+               if (IN6_IS_ADDR_UNSPECIFIED(&peer->nexthop.v6_global)) {
+#if defined(HAVE_CUMULUS)
+                       zlog_err(
+                               "%s: No local IPv6 addr resetting connection, fd %d",
+                               peer->host, peer->fd);
+                       bgp_notify_send(peer, BGP_NOTIFY_CEASE,
+                                       BGP_NOTIFY_SUBCODE_UNSPECIFIC);
+                       return -1;
 #endif
-        }
-    }
-  peer->rtt = sockopt_tcp_rtt (peer->fd);
-
-  if ((ret = bgp_event_update(peer, Receive_OPEN_message)) < 0)
-    {
-      zlog_err("%s: BGP event update failed for peer: %s", __FUNCTION__,
-              peer->host);
-      /* DD: bgp send notify and reset state */
-      return (ret);
-    }
-
-  peer->packet_size = 0;
-  if (peer->ibuf)
-    stream_reset (peer->ibuf);
-
-  return 0;
+               }
+       }
+       peer->rtt = sockopt_tcp_rtt(peer->fd);
+
+       if ((ret = bgp_event_update(peer, Receive_OPEN_message)) < 0) {
+               zlog_err("%s: BGP event update failed for peer: %s",
+                        __FUNCTION__, peer->host);
+               /* DD: bgp send notify and reset state */
+               return (ret);
+       }
+
+       peer->packet_size = 0;
+       if (peer->ibuf)
+               stream_reset(peer->ibuf);
+
+       return 0;
 }
 
-/* Called when there is a change in the EOR(implicit or explicit) status of a peer.
+/* Called when there is a change in the EOR(implicit or explicit) status of a
+   peer.
    Ends the update-delay if all expected peers are done with EORs. */
-void
-bgp_check_update_delay(struct bgp *bgp)
+void bgp_check_update_delay(struct bgp *bgp)
 {
-  struct listnode *node, *nnode;
-  struct peer *peer = NULL;
-
-  if (bgp_debug_neighbor_events(peer))
-    zlog_debug ("Checking update delay, T: %d R: %d I:%d E: %d", bgp->established,
-                bgp->restarted_peers, bgp->implicit_eors, bgp->explicit_eors);
-
-  if (bgp->established <=
-      bgp->restarted_peers + bgp->implicit_eors + bgp->explicit_eors)
-    {
-      /* This is an extra sanity check to make sure we wait for all the
-         eligible configured peers. This check is performed if establish wait
-         timer is on, or establish wait option is not given with the
-         update-delay command */
-      if (bgp->t_establish_wait ||
-          (bgp->v_establish_wait == bgp->v_update_delay))
-        for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
-          {
-            if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)
-                && !CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN)
-                && !peer->update_delay_over)
-              {
-                if (bgp_debug_neighbor_events(peer))
-                  zlog_debug (" Peer %s pending, continuing read-only mode",
-                              peer->host);
-                return;
-              }
-          }
-
-      zlog_info ("Update delay ended, restarted: %d, EORs implicit: %d, explicit: %d",
-                 bgp->restarted_peers, bgp->implicit_eors, bgp->explicit_eors);
-      bgp_update_delay_end(bgp);
-    }
+       struct listnode *node, *nnode;
+       struct peer *peer = NULL;
+
+       if (bgp_debug_neighbor_events(peer))
+               zlog_debug("Checking update delay, T: %d R: %d I:%d E: %d",
+                          bgp->established, bgp->restarted_peers,
+                          bgp->implicit_eors, bgp->explicit_eors);
+
+       if (bgp->established
+           <= bgp->restarted_peers + bgp->implicit_eors + bgp->explicit_eors) {
+               /* This is an extra sanity check to make sure we wait for all
+                  the
+                  eligible configured peers. This check is performed if
+                  establish wait
+                  timer is on, or establish wait option is not given with the
+                  update-delay command */
+               if (bgp->t_establish_wait
+                   || (bgp->v_establish_wait == bgp->v_update_delay))
+                       for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+                               if (CHECK_FLAG(peer->flags,
+                                              PEER_FLAG_CONFIG_NODE)
+                                   && !CHECK_FLAG(peer->flags,
+                                                  PEER_FLAG_SHUTDOWN)
+                                   && !peer->update_delay_over) {
+                                       if (bgp_debug_neighbor_events(peer))
+                                               zlog_debug(
+                                                       " Peer %s pending, continuing read-only mode",
+                                                       peer->host);
+                                       return;
+                               }
+                       }
+
+               zlog_info(
+                       "Update delay ended, restarted: %d, EORs implicit: %d, explicit: %d",
+                       bgp->restarted_peers, bgp->implicit_eors,
+                       bgp->explicit_eors);
+               bgp_update_delay_end(bgp);
+       }
 }
 
 /* Called if peer is known to have restarted. The restart-state bit in
    Graceful-Restart capability is used for that */
-void
-bgp_update_restarted_peers (struct peer *peer)
+void bgp_update_restarted_peers(struct peer *peer)
 {
-  if (!bgp_update_delay_active(peer->bgp)) return; /* BGP update delay has ended */
-  if (peer->update_delay_over) return; /* This peer has already been considered */
-
-  if (bgp_debug_neighbor_events(peer))
-    zlog_debug ("Peer %s: Checking restarted", peer->host);
-
-  if (peer->status == Established)
-    {
-      peer->update_delay_over = 1;
-      peer->bgp->restarted_peers++;
-      bgp_check_update_delay(peer->bgp);
-    }
+       if (!bgp_update_delay_active(peer->bgp))
+               return; /* BGP update delay has ended */
+       if (peer->update_delay_over)
+               return; /* This peer has already been considered */
+
+       if (bgp_debug_neighbor_events(peer))
+               zlog_debug("Peer %s: Checking restarted", peer->host);
+
+       if (peer->status == Established) {
+               peer->update_delay_over = 1;
+               peer->bgp->restarted_peers++;
+               bgp_check_update_delay(peer->bgp);
+       }
 }
 
 /* Called as peer receives a keep-alive. Determines if this occurence can be
    taken as an implicit EOR for this peer.
    NOTE: The very first keep-alive after the Established state of a peer is
-         considered implicit EOR for the update-delay purposes */
-void
-bgp_update_implicit_eors (struct peer *peer)
+        considered implicit EOR for the update-delay purposes */
+void bgp_update_implicit_eors(struct peer *peer)
 {
-  if (!bgp_update_delay_active(peer->bgp)) return; /* BGP update delay has ended */
-  if (peer->update_delay_over) return; /* This peer has already been considered */
-
-  if (bgp_debug_neighbor_events(peer))
-    zlog_debug ("Peer %s: Checking implicit EORs", peer->host);
-
-  if (peer->status == Established)
-    {
-      peer->update_delay_over = 1;
-      peer->bgp->implicit_eors++;
-      bgp_check_update_delay(peer->bgp);
-    }
+       if (!bgp_update_delay_active(peer->bgp))
+               return; /* BGP update delay has ended */
+       if (peer->update_delay_over)
+               return; /* This peer has already been considered */
+
+       if (bgp_debug_neighbor_events(peer))
+               zlog_debug("Peer %s: Checking implicit EORs", peer->host);
+
+       if (peer->status == Established) {
+               peer->update_delay_over = 1;
+               peer->bgp->implicit_eors++;
+               bgp_check_update_delay(peer->bgp);
+       }
 }
 
 /* Should be called only when there is a change in the EOR_RECEIVED status
    for any afi/safi on a peer */
-static void
-bgp_update_explicit_eors (struct peer *peer)
+static void bgp_update_explicit_eors(struct peer *peer)
 {
-  afi_t afi;
-  safi_t safi;
-
-  if (!bgp_update_delay_active(peer->bgp)) return; /* BGP update delay has ended */
-  if (peer->update_delay_over) return; /* This peer has already been considered */
-
-  if (bgp_debug_neighbor_events(peer))
-    zlog_debug ("Peer %s: Checking explicit EORs", peer->host);
-
-  for (afi = AFI_IP; afi < AFI_MAX; afi++)
-    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
-      {
-        if (peer->afc_nego[afi][safi] &&
-            !CHECK_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_EOR_RECEIVED))
-          {
-            if (bgp_debug_neighbor_events(peer))
-              zlog_debug ("   afi %d safi %d didnt receive EOR", afi, safi);
-            return;
-          }
-      }
-
-  peer->update_delay_over = 1;
-  peer->bgp->explicit_eors++;
-  bgp_check_update_delay(peer->bgp);
+       afi_t afi;
+       safi_t safi;
+
+       if (!bgp_update_delay_active(peer->bgp))
+               return; /* BGP update delay has ended */
+       if (peer->update_delay_over)
+               return; /* This peer has already been considered */
+
+       if (bgp_debug_neighbor_events(peer))
+               zlog_debug("Peer %s: Checking explicit EORs", peer->host);
+
+       for (afi = AFI_IP; afi < AFI_MAX; afi++)
+               for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
+                       if (peer->afc_nego[afi][safi]
+                           && !CHECK_FLAG(peer->af_sflags[afi][safi],
+                                          PEER_STATUS_EOR_RECEIVED)) {
+                               if (bgp_debug_neighbor_events(peer))
+                                       zlog_debug(
+                                               "   afi %d safi %d didnt receive EOR",
+                                               afi, safi);
+                               return;
+                       }
+               }
+
+       peer->update_delay_over = 1;
+       peer->bgp->explicit_eors++;
+       bgp_check_update_delay(peer->bgp);
 }
 
-/* Frontend for NLRI parsing, to fan-out to AFI/SAFI specific parsers 
- * mp_withdraw, if set, is used to nullify attr structure on most of the calling safi function
+/* Frontend for NLRI parsing, to fan-out to AFI/SAFI specific parsers
+ * mp_withdraw, if set, is used to nullify attr structure on most of the calling
+ * safi function
  * and for evpn, passed as parameter
  */
-int
-bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet, int mp_withdraw)
+int bgp_nlri_parse(struct peer *peer, struct attr *attr,
+                  struct bgp_nlri *packet, int mp_withdraw)
 {
-  switch (packet->safi)
-    {
-      case SAFI_UNICAST:
-      case SAFI_MULTICAST:
-        return bgp_nlri_parse_ip (peer, mp_withdraw?NULL:attr, packet);
-      case SAFI_LABELED_UNICAST:
-        return bgp_nlri_parse_label (peer, mp_withdraw?NULL:attr, packet);
-      case SAFI_MPLS_VPN:
-        return bgp_nlri_parse_vpn (peer, mp_withdraw?NULL:attr, packet);
-      case SAFI_EVPN:
-        return bgp_nlri_parse_evpn (peer, attr, packet, mp_withdraw);
-    }
-  return -1;
+       switch (packet->safi) {
+       case SAFI_UNICAST:
+       case SAFI_MULTICAST:
+               return bgp_nlri_parse_ip(peer, mp_withdraw ? NULL : attr,
+                                        packet);
+       case SAFI_LABELED_UNICAST:
+               return bgp_nlri_parse_label(peer, mp_withdraw ? NULL : attr,
+                                           packet);
+       case SAFI_MPLS_VPN:
+               return bgp_nlri_parse_vpn(peer, mp_withdraw ? NULL : attr,
+                                         packet);
+       case SAFI_EVPN:
+               return bgp_nlri_parse_evpn(peer, attr, packet, mp_withdraw);
+       }
+       return -1;
 }
 
 /* Parse BGP Update packet and make attribute object. */
-static int
-bgp_update_receive (struct peer *peer, bgp_size_t size)
+static int bgp_update_receive(struct peer *peer, bgp_size_t size)
 {
-  int ret, nlri_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;
-
-  enum NLRI_TYPES {
-    NLRI_UPDATE,
-    NLRI_WITHDRAW,
-    NLRI_MP_UPDATE,
-    NLRI_MP_WITHDRAW,
-    NLRI_TYPE_MAX
-  };
-  struct bgp_nlri nlris[NLRI_TYPE_MAX];
-
-  /* Status must be Established. */
-  if (peer->status != Established) 
-    {
-      zlog_err ("%s [FSM] Update packet received under status %s",
-               peer->host, lookup_msg(bgp_status_msg, peer->status, NULL));
-      bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
-      return -1;
-    }
-
-  /* Set initial values. */
-  memset (&attr, 0, sizeof (struct attr));
-  attr.label_index = BGP_INVALID_LABEL_INDEX;
-  attr.label = MPLS_INVALID_LABEL;
-  memset (&nlris, 0, sizeof (nlris));
-  memset (peer->rcvd_attr_str, 0, BUFSIZ);
-  peer->rcvd_attr_printed = 0;
-
-  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)
-    {
-      nlris[NLRI_WITHDRAW].afi = AFI_IP;
-      nlris[NLRI_WITHDRAW].safi = SAFI_UNICAST;
-      nlris[NLRI_WITHDRAW].nlri = stream_pnt (s);
-      nlris[NLRI_WITHDRAW].length = withdraw_len;
-      stream_forward_getp (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;
-    }
-  
-  /* Certain attribute parsing errors should not be considered bad enough
-   * to reset the session for, most particularly any partial/optional
-   * attributes that have 'tunneled' over speakers that don't understand
-   * them. Instead we withdraw only the prefix concerned.
-   * 
-   * Complicates the flow a little though..
-   */
-  bgp_attr_parse_ret_t attr_parse_ret = BGP_ATTR_PARSE_PROCEED;
-  /* This define morphs the update case into a withdraw when lower levels
-   * have signalled an error condition where this is best.
-   */
+       int ret, nlri_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;
+
+       enum NLRI_TYPES {
+               NLRI_UPDATE,
+               NLRI_WITHDRAW,
+               NLRI_MP_UPDATE,
+               NLRI_MP_WITHDRAW,
+               NLRI_TYPE_MAX
+       };
+       struct bgp_nlri nlris[NLRI_TYPE_MAX];
+
+       /* Status must be Established. */
+       if (peer->status != Established) {
+               zlog_err("%s [FSM] Update packet received under status %s",
+                        peer->host,
+                        lookup_msg(bgp_status_msg, peer->status, NULL));
+               bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR, 0);
+               return -1;
+       }
+
+       /* Set initial values. */
+       memset(&attr, 0, sizeof(struct attr));
+       attr.label_index = BGP_INVALID_LABEL_INDEX;
+       attr.label = MPLS_INVALID_LABEL;
+       memset(&nlris, 0, sizeof(nlris));
+       memset(peer->rcvd_attr_str, 0, BUFSIZ);
+       peer->rcvd_attr_printed = 0;
+
+       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) {
+               nlris[NLRI_WITHDRAW].afi = AFI_IP;
+               nlris[NLRI_WITHDRAW].safi = SAFI_UNICAST;
+               nlris[NLRI_WITHDRAW].nlri = stream_pnt(s);
+               nlris[NLRI_WITHDRAW].length = withdraw_len;
+               stream_forward_getp(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;
+       }
+
+       /* Certain attribute parsing errors should not be considered bad enough
+        * to reset the session for, most particularly any partial/optional
+        * attributes that have 'tunneled' over speakers that don't understand
+        * them. Instead we withdraw only the prefix concerned.
+        *
+        * Complicates the flow a little though..
+        */
+       bgp_attr_parse_ret_t attr_parse_ret = BGP_ATTR_PARSE_PROCEED;
+/* This define morphs the update case into a withdraw when lower levels
+ * have signalled an error condition where this is best.
+ */
 #define NLRI_ATTR_ARG (attr_parse_ret != BGP_ATTR_PARSE_WITHDRAW ? &attr : NULL)
 
-  /* Parse attribute when it exists. */
-  if (attribute_len)
-    {
-      attr_parse_ret = bgp_attr_parse (peer, &attr, attribute_len, 
-                           &nlris[NLRI_MP_UPDATE], &nlris[NLRI_MP_WITHDRAW]);
-      if (attr_parse_ret == BGP_ATTR_PARSE_ERROR)
-       {
-         bgp_attr_unintern_sub (&attr);
-         return -1;
+       /* Parse attribute when it exists. */
+       if (attribute_len) {
+               attr_parse_ret = bgp_attr_parse(peer, &attr, attribute_len,
+                                               &nlris[NLRI_MP_UPDATE],
+                                               &nlris[NLRI_MP_WITHDRAW]);
+               if (attr_parse_ret == BGP_ATTR_PARSE_ERROR) {
+                       bgp_attr_unintern_sub(&attr);
+                       return -1;
+               }
+       }
+
+       /* Logging the attribute. */
+       if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW
+           || BGP_DEBUG(update, UPDATE_IN)
+           || BGP_DEBUG(update, UPDATE_PREFIX)) {
+               ret = bgp_dump_attr(&attr, peer->rcvd_attr_str, BUFSIZ);
+
+               if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
+                       zlog_err(
+                               "%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
+                               peer->host);
+
+               if (ret && bgp_debug_update(peer, NULL, NULL, 1)) {
+                       zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
+                                  peer->rcvd_attr_str);
+                       peer->rcvd_attr_printed = 1;
+               }
+       }
+
+       /* Network Layer Reachability Information. */
+       update_len = end - stream_pnt(s);
+
+       if (update_len) {
+               /* Set NLRI portion to structure. */
+               nlris[NLRI_UPDATE].afi = AFI_IP;
+               nlris[NLRI_UPDATE].safi = SAFI_UNICAST;
+               nlris[NLRI_UPDATE].nlri = stream_pnt(s);
+               nlris[NLRI_UPDATE].length = update_len;
+               stream_forward_getp(s, update_len);
+       }
+
+       if (BGP_DEBUG(update, UPDATE_IN))
+               zlog_debug("%s rcvd UPDATE wlen %d attrlen %d alen %d",
+                          peer->host, withdraw_len, attribute_len, update_len);
+
+       /* Parse any given NLRIs */
+       for (int i = NLRI_UPDATE; i < NLRI_TYPE_MAX; i++) {
+               if (!nlris[i].nlri)
+                       continue;
+
+               /* NLRI is processed iff the peer if configured for the specific
+                * afi/safi */
+               if (!peer->afc[nlris[i].afi][nlris[i].safi]) {
+                       zlog_info(
+                               "%s [Info] UPDATE for non-enabled AFI/SAFI %u/%u",
+                               peer->host, nlris[i].afi, nlris[i].safi);
+                       continue;
+               }
+
+               /* EoR handled later */
+               if (nlris[i].length == 0)
+                       continue;
+
+               switch (i) {
+               case NLRI_UPDATE:
+               case NLRI_MP_UPDATE:
+                       nlri_ret = bgp_nlri_parse(peer, NLRI_ATTR_ARG,
+                                                 &nlris[i], 0);
+                       break;
+               case NLRI_WITHDRAW:
+               case NLRI_MP_WITHDRAW:
+                       nlri_ret = bgp_nlri_parse(peer, &attr, &nlris[i], 1);
+                       break;
+               default:
+                       nlri_ret = -1;
+               }
+
+               if (nlri_ret < 0) {
+                       zlog_err("%s [Error] Error parsing NLRI", peer->host);
+                       if (peer->status == Established)
+                               bgp_notify_send(
+                                       peer, BGP_NOTIFY_UPDATE_ERR,
+                                       i <= NLRI_WITHDRAW
+                                               ? BGP_NOTIFY_UPDATE_INVAL_NETWORK
+                                               : BGP_NOTIFY_UPDATE_OPT_ATTR_ERR);
+                       bgp_attr_unintern_sub(&attr);
+                       return -1;
+               }
+       }
+
+       /* EoR checks
+        *
+        * Non-MP IPv4/Unicast EoR is a completely empty UPDATE
+        * and MP EoR should have only an empty MP_UNREACH
+        */
+       if (!update_len && !withdraw_len && nlris[NLRI_MP_UPDATE].length == 0) {
+               afi_t afi = 0;
+               safi_t safi;
+
+               /* Non-MP IPv4/Unicast is a completely emtpy UPDATE - already
+                * checked
+                * update and withdraw NLRI lengths are 0.
+                */
+               if (!attribute_len) {
+                       afi = AFI_IP;
+                       safi = SAFI_UNICAST;
+               } else if (attr.flag & ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI)
+                          && nlris[NLRI_MP_WITHDRAW].length == 0) {
+                       afi = nlris[NLRI_MP_WITHDRAW].afi;
+                       safi = nlris[NLRI_MP_WITHDRAW].safi;
+               }
+
+               if (afi && peer->afc[afi][safi]) {
+                       /* End-of-RIB received */
+                       if (!CHECK_FLAG(peer->af_sflags[afi][safi],
+                                       PEER_STATUS_EOR_RECEIVED)) {
+                               SET_FLAG(peer->af_sflags[afi][safi],
+                                        PEER_STATUS_EOR_RECEIVED);
+                               bgp_update_explicit_eors(peer);
+                       }
+
+                       /* NSF delete stale route */
+                       if (peer->nsf[afi][safi])
+                               bgp_clear_stale_route(peer, afi, safi);
+
+                       if (bgp_debug_neighbor_events(peer)) {
+                               zlog_debug("rcvd End-of-RIB for %s from %s",
+                                          afi_safi_print(afi, safi),
+                                          peer->host);
+                       }
+               }
        }
-    }
-  
-  /* Logging the attribute. */
-  if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW ||
-      BGP_DEBUG (update, UPDATE_IN) ||
-      BGP_DEBUG (update, UPDATE_PREFIX))
-    {
-      ret = bgp_dump_attr (&attr, peer->rcvd_attr_str, BUFSIZ);
-      
-      if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
-        zlog_err ("%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
-                  peer->host);
-
-      if (ret && bgp_debug_update(peer, NULL, NULL, 1))
-        {
-          zlog_debug ("%s rcvd UPDATE w/ attr: %s", peer->host, peer->rcvd_attr_str);
-          peer->rcvd_attr_printed = 1;
-        }
-    }
-  
-  /* Network Layer Reachability Information. */
-  update_len = end - stream_pnt (s);
-
-  if (update_len)
-    {
-      /* Set NLRI portion to structure. */
-      nlris[NLRI_UPDATE].afi = AFI_IP;
-      nlris[NLRI_UPDATE].safi = SAFI_UNICAST;
-      nlris[NLRI_UPDATE].nlri = stream_pnt (s);
-      nlris[NLRI_UPDATE].length = update_len;
-      stream_forward_getp (s, update_len);
-    }
-
-  if (BGP_DEBUG (update, UPDATE_IN))
-    zlog_debug("%s rcvd UPDATE wlen %d attrlen %d alen %d",
-               peer->host, withdraw_len, attribute_len, update_len);
-
-  /* Parse any given NLRIs */
-  for (int i = NLRI_UPDATE; i < NLRI_TYPE_MAX; i++)
-    {
-      if (!nlris[i].nlri)
-        continue;
-
-      /* NLRI is processed iff the peer if configured for the specific afi/safi */
-      if (!peer->afc[nlris[i].afi][nlris[i].safi])
-        {
-          zlog_info ("%s [Info] UPDATE for non-enabled AFI/SAFI %u/%u",
-                     peer->host, nlris[i].afi, nlris[i].safi);
-          continue;
-        }
-
-      /* EoR handled later */
-      if (nlris[i].length == 0)
-        continue;
-
-      switch (i)
-        {
-          case NLRI_UPDATE:
-          case NLRI_MP_UPDATE:
-            nlri_ret = bgp_nlri_parse (peer, NLRI_ATTR_ARG, &nlris[i], 0);
-            break;
-          case NLRI_WITHDRAW:
-          case NLRI_MP_WITHDRAW:
-            nlri_ret = bgp_nlri_parse (peer, &attr, &nlris[i], 1);
-            break;
-          default:
-            nlri_ret = -1;
-        }
-
-      if (nlri_ret < 0)
-        {
-          zlog_err("%s [Error] Error parsing NLRI", peer->host);
-          if (peer->status == Established)
-            bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
-                             i <= NLRI_WITHDRAW ? BGP_NOTIFY_UPDATE_INVAL_NETWORK
-                                                : BGP_NOTIFY_UPDATE_OPT_ATTR_ERR);
-          bgp_attr_unintern_sub (&attr);
-          return -1;
-        }
-    }
-
-  /* EoR checks
-   *
-   * Non-MP IPv4/Unicast EoR is a completely empty UPDATE
-   * and MP EoR should have only an empty MP_UNREACH
-   */
-  if (!update_len && !withdraw_len
-      && nlris[NLRI_MP_UPDATE].length == 0)
-    {
-      afi_t afi = 0;
-      safi_t safi;
-
-      /* Non-MP IPv4/Unicast is a completely emtpy UPDATE - already checked
-       * update and withdraw NLRI lengths are 0.
-       */
-      if (!attribute_len)
-        {
-          afi = AFI_IP;
-          safi = SAFI_UNICAST;
-        }
-      else if (attr.flag & ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI)
-               && nlris[NLRI_MP_WITHDRAW].length == 0)
-        {
-          afi = nlris[NLRI_MP_WITHDRAW].afi;
-          safi = nlris[NLRI_MP_WITHDRAW].safi;
-        }
-
-      if (afi && peer->afc[afi][safi])
-        {
-          /* End-of-RIB received */
-          if (!CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_RECEIVED))
-            {
-              SET_FLAG (peer->af_sflags[afi][safi],
-                        PEER_STATUS_EOR_RECEIVED);
-              bgp_update_explicit_eors(peer);
-            }
-
-          /* NSF delete stale route */
-          if (peer->nsf[afi][safi])
-            bgp_clear_stale_route (peer, afi, safi);
-
-          if (bgp_debug_neighbor_events(peer))
-            {
-              zlog_debug ("rcvd End-of-RIB for %s from %s",
-                          afi_safi_print (afi, safi), peer->host);
-            }
-        }
-    }
-
-  /* Everything is done.  We unintern temporary structures which
-     interned in bgp_attr_parse(). */
-  bgp_attr_unintern_sub (&attr);
-
-  /* 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 = bgp_clock ();
-
-  /* Rearm holdtime timer */
-  BGP_TIMER_OFF (peer->t_holdtime);
-  bgp_timer_set (peer);
-
-  return 0;
+
+       /* Everything is done.  We unintern temporary structures which
+          interned in bgp_attr_parse(). */
+       bgp_attr_unintern_sub(&attr);
+
+       /* 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 = bgp_clock();
+
+       /* Rearm holdtime timer */
+       BGP_TIMER_OFF(peer->t_holdtime);
+       bgp_timer_set(peer);
+
+       return 0;
 }
 
 /* Notify message treatment function. */
-static void
-bgp_notify_receive (struct peer *peer, bgp_size_t size)
+static 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.raw_data = (u_char*)peer->notify.data;
-      }
-
-    bgp_notify_print(peer, &bgp_notify, "received");
-    if (bgp_notify.data)
-      {
-        XFREE (MTYPE_TMP, bgp_notify.data);
-        bgp_notify.data = NULL;
-        bgp_notify.length = 0;
-      }
-  }
-
-  /* peer count update */
-  peer->notify_in++;
-
-  peer->last_reset = PEER_DOWN_NOTIFY_RECEIVED;
-
-  /* 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);
-
-  BGP_EVENT_ADD (peer, Receive_NOTIFICATION_message);
+       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.raw_data = (u_char *)peer->notify.data;
+               }
+
+               bgp_notify_print(peer, &bgp_notify, "received");
+               if (bgp_notify.data) {
+                       XFREE(MTYPE_TMP, bgp_notify.data);
+                       bgp_notify.data = NULL;
+                       bgp_notify.length = 0;
+               }
+       }
+
+       /* peer count update */
+       peer->notify_in++;
+
+       peer->last_reset = PEER_DOWN_NOTIFY_RECEIVED;
+
+       /* 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);
+
+       BGP_EVENT_ADD(peer, Receive_NOTIFICATION_message);
 }
 
 /* Keepalive treatment function -- get keepalive send keepalive */
-static void
-bgp_keepalive_receive (struct peer *peer, bgp_size_t size)
+static void bgp_keepalive_receive(struct peer *peer, bgp_size_t size)
 {
-  if (bgp_debug_keepalive(peer))
-    zlog_debug ("%s KEEPALIVE rcvd", peer->host); 
-  
-  BGP_EVENT_ADD (peer, Receive_KEEPALIVE_message);
+       if (bgp_debug_keepalive(peer))
+               zlog_debug("%s KEEPALIVE rcvd", peer->host);
+
+       BGP_EVENT_ADD(peer, Receive_KEEPALIVE_message);
 }
 
 /* Route refresh message is received. */
-static void
-bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
+static void bgp_route_refresh_receive(struct peer *peer, bgp_size_t size)
 {
-  iana_afi_t pkt_afi;
-  afi_t afi;
-  safi_t pkt_safi, safi;
-  struct stream *s;
-  struct peer_af *paf;
-  struct update_group *updgrp;
-  struct peer *updgrp_peer;
-
-  /* If peer does not have the capability, send notification. */
-  if (! CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_ADV))
-    {
-      zlog_err ("%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) 
-    {
-      zlog_err ("%s [Error] Route refresh packet received under status %s",
-               peer->host, lookup_msg(bgp_status_msg, peer->status, NULL));
-      bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
-      return;
-    }
-
-  s = peer->ibuf;
-  
-  /* Parse packet. */
-  pkt_afi = stream_getw (s);
-  (void)stream_getc (s);
-  pkt_safi = stream_getc (s);
-
-  if (bgp_debug_update(peer, NULL, NULL, 0))
-    zlog_debug ("%s rcvd REFRESH_REQ for afi/safi: %d/%d",
-              peer->host, pkt_afi, pkt_safi);
-
-  /* Convert AFI, SAFI to internal values and check. */
-  if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi))
-    {
-      zlog_info ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored",
-                peer->host, pkt_afi, pkt_safi);
-      return;
-    }
-
-  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) + 2) < end)
-       {
-         orf_type = stream_getc (s); 
-         orf_len = stream_getw (s);
-         
-         /* orf_len in bounds? */
-         if ((stream_pnt (s) + orf_len) > end)
-           break; /* XXX: Notify instead?? */
-         if (orf_type == ORF_TYPE_PREFIX
-             || orf_type == ORF_TYPE_PREFIX_OLD)
-           {
-             uint8_t *p_pnt = stream_pnt (s);
-             uint8_t *p_end = stream_pnt (s) + orf_len;
-             struct orf_prefix orfp;
-             u_char common = 0;
-             u_int32_t seq;
-             int psize;
-             char name[BUFSIZ];
-             int ret = CMD_SUCCESS;
-
-              if (bgp_debug_neighbor_events(peer))
-               {
-                 zlog_debug ("%s rcvd Prefixlist ORF(%d) length %d",
-                            peer->host, orf_type, orf_len);
+       iana_afi_t pkt_afi;
+       afi_t afi;
+       safi_t pkt_safi, safi;
+       struct stream *s;
+       struct peer_af *paf;
+       struct update_group *updgrp;
+       struct peer *updgrp_peer;
+
+       /* If peer does not have the capability, send notification. */
+       if (!CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_ADV)) {
+               zlog_err("%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) {
+               zlog_err(
+                       "%s [Error] Route refresh packet received under status %s",
+                       peer->host,
+                       lookup_msg(bgp_status_msg, peer->status, NULL));
+               bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR, 0);
+               return;
+       }
+
+       s = peer->ibuf;
+
+       /* Parse packet. */
+       pkt_afi = stream_getw(s);
+       (void)stream_getc(s);
+       pkt_safi = stream_getc(s);
+
+       if (bgp_debug_update(peer, NULL, NULL, 0))
+               zlog_debug("%s rcvd REFRESH_REQ for afi/safi: %d/%d",
+                          peer->host, pkt_afi, pkt_safi);
+
+       /* Convert AFI, SAFI to internal values and check. */
+       if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
+               zlog_info(
+                       "%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored",
+                       peer->host, pkt_afi, pkt_safi);
+               return;
+       }
+
+       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;
                }
 
-              /* we're going to read at least 1 byte of common ORF header,
-               * and 7 bytes of ORF Address-filter entry from the stream
-               */
-              if (orf_len < 7)
-                break; 
-                
-             /* ORF prefix-list name */
-             sprintf (name, "%s.%d.%d", peer->host, afi, safi);
-
-             while (p_pnt < p_end)
-               {
-                  /* If the ORF entry is malformed, want to read as much of it
-                   * as possible without going beyond the bounds of the entry,
-                   * to maximise debug information.
-                   */
-                 int ok;
-                 memset (&orfp, 0, sizeof (struct orf_prefix));
-                 common = *p_pnt++;
-                 /* after ++: p_pnt <= p_end */
-                 if (common & ORF_COMMON_PART_REMOVE_ALL)
-                   {
-                      if (bgp_debug_neighbor_events(peer))
-                       zlog_debug ("%s rcvd Remove-All pfxlist ORF request", peer->host);
-                     prefix_bgp_orf_remove_all (afi, name);
-                     break;
-                   }
-                 ok = ((u_int32_t)(p_end - p_pnt) >= sizeof(u_int32_t)) ;
-                 if (ok)
-                   {
-                     memcpy (&seq, p_pnt, sizeof (u_int32_t));
-                      p_pnt += sizeof (u_int32_t);
-                      orfp.seq = ntohl (seq);
-                   }
-                 else
-                   p_pnt = p_end ;
-
-                 if ((ok = (p_pnt < p_end)))
-                   orfp.ge = *p_pnt++ ;      /* value checked in prefix_bgp_orf_set() */
-                 if ((ok = (p_pnt < p_end)))
-                   orfp.le = *p_pnt++ ;      /* value checked in prefix_bgp_orf_set() */
-                 if ((ok = (p_pnt < p_end)))
-                   orfp.p.prefixlen = *p_pnt++ ;
-                 orfp.p.family = afi2family (afi);   /* afi checked already  */
-
-                 psize = PSIZE (orfp.p.prefixlen);   /* 0 if not ok          */
-                 if (psize > prefix_blen(&orfp.p))   /* valid for family ?   */
-                   {
-                     ok = 0 ;
-                     psize = prefix_blen(&orfp.p) ;
-                   }
-                 if (psize > (p_end - p_pnt))        /* valid for packet ?   */
-                   {
-                     ok = 0 ;
-                     psize = p_end - p_pnt ;
-                   }
-
-                 if (psize > 0)
-                   memcpy (&orfp.p.u.prefix, p_pnt, psize);
-                 p_pnt += psize;
-
-                  if (bgp_debug_neighbor_events(peer))
-                   {
-                     char buf[INET6_BUFSIZ];
-
-                     zlog_debug ("%s rcvd %s %s seq %u %s/%d ge %d le %d%s",
-                                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, INET6_BUFSIZ),
-                                orfp.p.prefixlen, orfp.ge, orfp.le,
-                                ok ? "" : " MALFORMED");
-                   }
-
-                 if (ok)
-                   ret = prefix_bgp_orf_set (name, afi, &orfp,
-                                  (common & ORF_COMMON_PART_DENY ? 0 : 1 ),
-                                  (common & ORF_COMMON_PART_REMOVE ? 0 : 1));
-
-                 if (!ok || (ok && ret != CMD_SUCCESS))
-                   {
-                     zlog_info ("%s Received misformatted prefixlist ORF."
-                                " Remove All pfxlist", peer->host);
-                     prefix_bgp_orf_remove_all (afi, name);
-                     break;
-                   }
+               when_to_refresh = stream_getc(s);
+               end = stream_pnt(s) + (size - 5);
+
+               while ((stream_pnt(s) + 2) < end) {
+                       orf_type = stream_getc(s);
+                       orf_len = stream_getw(s);
+
+                       /* orf_len in bounds? */
+                       if ((stream_pnt(s) + orf_len) > end)
+                               break; /* XXX: Notify instead?? */
+                       if (orf_type == ORF_TYPE_PREFIX
+                           || orf_type == ORF_TYPE_PREFIX_OLD) {
+                               uint8_t *p_pnt = stream_pnt(s);
+                               uint8_t *p_end = stream_pnt(s) + orf_len;
+                               struct orf_prefix orfp;
+                               u_char common = 0;
+                               u_int32_t seq;
+                               int psize;
+                               char name[BUFSIZ];
+                               int ret = CMD_SUCCESS;
+
+                               if (bgp_debug_neighbor_events(peer)) {
+                                       zlog_debug(
+                                               "%s rcvd Prefixlist ORF(%d) length %d",
+                                               peer->host, orf_type, orf_len);
+                               }
+
+                               /* we're going to read at least 1 byte of common
+                                * ORF header,
+                                * and 7 bytes of ORF Address-filter entry from
+                                * the stream
+                                */
+                               if (orf_len < 7)
+                                       break;
+
+                               /* ORF prefix-list name */
+                               sprintf(name, "%s.%d.%d", peer->host, afi,
+                                       safi);
+
+                               while (p_pnt < p_end) {
+                                       /* If the ORF entry is malformed, want
+                                        * to read as much of it
+                                        * as possible without going beyond the
+                                        * bounds of the entry,
+                                        * to maximise debug information.
+                                        */
+                                       int ok;
+                                       memset(&orfp, 0,
+                                              sizeof(struct orf_prefix));
+                                       common = *p_pnt++;
+                                       /* after ++: p_pnt <= p_end */
+                                       if (common
+                                           & ORF_COMMON_PART_REMOVE_ALL) {
+                                               if (bgp_debug_neighbor_events(
+                                                           peer))
+                                                       zlog_debug(
+                                                               "%s rcvd Remove-All pfxlist ORF request",
+                                                               peer->host);
+                                               prefix_bgp_orf_remove_all(afi,
+                                                                         name);
+                                               break;
+                                       }
+                                       ok = ((u_int32_t)(p_end - p_pnt)
+                                             >= sizeof(u_int32_t));
+                                       if (ok) {
+                                               memcpy(&seq, p_pnt,
+                                                      sizeof(u_int32_t));
+                                               p_pnt += sizeof(u_int32_t);
+                                               orfp.seq = ntohl(seq);
+                                       } else
+                                               p_pnt = p_end;
+
+                                       if ((ok = (p_pnt < p_end)))
+                                               orfp.ge =
+                                                       *p_pnt++; /* value
+                                                                    checked in
+                                                                    prefix_bgp_orf_set()
+                                                                    */
+                                       if ((ok = (p_pnt < p_end)))
+                                               orfp.le =
+                                                       *p_pnt++; /* value
+                                                                    checked in
+                                                                    prefix_bgp_orf_set()
+                                                                    */
+                                       if ((ok = (p_pnt < p_end)))
+                                               orfp.p.prefixlen = *p_pnt++;
+                                       orfp.p.family = afi2family(
+                                               afi); /* afi checked already  */
+
+                                       psize = PSIZE(
+                                               orfp.p.prefixlen); /* 0 if not
+                                                                     ok */
+                                       if (psize
+                                           > prefix_blen(
+                                                     &orfp.p)) /* valid for
+                                                                  family ?   */
+                                       {
+                                               ok = 0;
+                                               psize = prefix_blen(&orfp.p);
+                                       }
+                                       if (psize
+                                           > (p_end - p_pnt)) /* valid for
+                                                                 packet ?   */
+                                       {
+                                               ok = 0;
+                                               psize = p_end - p_pnt;
+                                       }
+
+                                       if (psize > 0)
+                                               memcpy(&orfp.p.u.prefix, p_pnt,
+                                                      psize);
+                                       p_pnt += psize;
+
+                                       if (bgp_debug_neighbor_events(peer)) {
+                                               char buf[INET6_BUFSIZ];
+
+                                               zlog_debug(
+                                                       "%s rcvd %s %s seq %u %s/%d ge %d le %d%s",
+                                                       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,
+                                                               INET6_BUFSIZ),
+                                                       orfp.p.prefixlen,
+                                                       orfp.ge, orfp.le,
+                                                       ok ? "" : " MALFORMED");
+                                       }
+
+                                       if (ok)
+                                               ret = prefix_bgp_orf_set(
+                                                       name, afi, &orfp,
+                                                       (common & ORF_COMMON_PART_DENY
+                                                                ? 0
+                                                                : 1),
+                                                       (common & ORF_COMMON_PART_REMOVE
+                                                                ? 0
+                                                                : 1));
+
+                                       if (!ok || (ok && ret != CMD_SUCCESS)) {
+                                               zlog_info(
+                                                       "%s Received misformatted prefixlist ORF."
+                                                       " Remove All pfxlist",
+                                                       peer->host);
+                                               prefix_bgp_orf_remove_all(afi,
+                                                                         name);
+                                               break;
+                                       }
+                               }
+
+                               peer->orf_plist[afi][safi] =
+                                       prefix_bgp_orf_lookup(afi, name);
+                       }
+                       stream_forward_getp(s, orf_len);
                }
+               if (bgp_debug_neighbor_events(peer))
+                       zlog_debug("%s rcvd Refresh %s ORF request", peer->host,
+                                  when_to_refresh == REFRESH_DEFER
+                                          ? "Defer"
+                                          : "Immediate");
+               if (when_to_refresh == REFRESH_DEFER)
+                       return;
+       }
 
-             peer->orf_plist[afi][safi] = prefix_bgp_orf_lookup (afi, name);
-           }
-         stream_forward_getp (s, orf_len);
+       /* 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);
+
+       paf = peer_af_find(peer, afi, safi);
+       if (paf && paf->subgroup) {
+               if (peer->orf_plist[afi][safi]) {
+                       updgrp = PAF_UPDGRP(paf);
+                       updgrp_peer = UPDGRP_PEER(updgrp);
+                       updgrp_peer->orf_plist[afi][safi] =
+                               peer->orf_plist[afi][safi];
+               }
+
+               /* If the peer is configured for default-originate clear the
+                * SUBGRP_STATUS_DEFAULT_ORIGINATE flag so that we will
+                * re-advertise the
+                * default
+                */
+               if (CHECK_FLAG(paf->subgroup->sflags,
+                              SUBGRP_STATUS_DEFAULT_ORIGINATE))
+                       UNSET_FLAG(paf->subgroup->sflags,
+                                  SUBGRP_STATUS_DEFAULT_ORIGINATE);
        }
-      if (bgp_debug_neighbor_events(peer))
-       zlog_debug ("%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);
-
-  paf = peer_af_find (peer, afi, safi);
-  if (paf && paf->subgroup)
-    {
-      if (peer->orf_plist[afi][safi])
-        {
-          updgrp = PAF_UPDGRP(paf);
-          updgrp_peer = UPDGRP_PEER(updgrp);
-          updgrp_peer->orf_plist[afi][safi] = peer->orf_plist[afi][safi];
-        }
-
-      /* If the peer is configured for default-originate clear the
-       * SUBGRP_STATUS_DEFAULT_ORIGINATE flag so that we will re-advertise the
-       * default
-       */
-      if (CHECK_FLAG (paf->subgroup->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE))
-        UNSET_FLAG (paf->subgroup->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE);
-    }
-
-  /* Perform route refreshment to the peer */
-  bgp_announce_route (peer, afi, safi);
+
+       /* Perform route refreshment to the peer */
+       bgp_announce_route(peer, afi, safi);
 }
 
-static int
-bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
+static int bgp_capability_msg_parse(struct peer *peer, u_char *pnt,
+                                   bgp_size_t length)
 {
-  u_char *end;
-  struct capability_mp_data mpc;
-  struct capability_header *hdr;
-  u_char action;
-  iana_afi_t pkt_afi;
-  afi_t afi;
-  safi_t pkt_safi, safi;
-
-  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;
-      hdr = (struct capability_header *)(pnt + 1);
-      
-      /* 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_neighbor_events(peer))
-       zlog_debug ("%s CAPABILITY has action: %d, code: %u, length %u",
-                  peer->host, action, hdr->code, hdr->length);
-
-      /* Capability length check. */
-      if ((pnt + hdr->length + 3) > end)
-        {
-          zlog_info ("%s Capability length error", peer->host);
-          bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
-          return -1;
-        }
-
-      /* Fetch structure to the byte stream. */
-      memcpy (&mpc, pnt + 3, sizeof (struct capability_mp_data));
-
-      /* We know MP Capability Code. */
-      if (hdr->code == CAPABILITY_CODE_MP)
-        {
-         pkt_afi = ntohs (mpc.afi);
-         pkt_safi = mpc.safi;
-
-          /* Ignore capability when override-capability is set. */
-          if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
-           continue;
-          
-          /* Convert AFI, SAFI to internal values. */
-          if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi))
-            {
-              if (bgp_debug_neighbor_events(peer))
-                zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid "
-                            "(%u/%u)", peer->host, pkt_afi, pkt_safi);
-              continue;
-            }
-          
-         /* Address family check.  */
-          if (bgp_debug_neighbor_events(peer))
-            zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u",
-                       peer->host,
-                       action == CAPABILITY_ACTION_SET 
-                       ? "Advertising" : "Removing",
-                       pkt_afi, pkt_safi);
-              
-          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
-        {
-          zlog_warn ("%s unrecognized capability code: %d - ignored",
-                     peer->host, hdr->code);
-        }
-      pnt += hdr->length + 3;
-    }
-  return 0;
+       u_char *end;
+       struct capability_mp_data mpc;
+       struct capability_header *hdr;
+       u_char action;
+       iana_afi_t pkt_afi;
+       afi_t afi;
+       safi_t pkt_safi, safi;
+
+       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;
+               hdr = (struct capability_header *)(pnt + 1);
+
+               /* 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_neighbor_events(peer))
+                       zlog_debug(
+                               "%s CAPABILITY has action: %d, code: %u, length %u",
+                               peer->host, action, hdr->code, hdr->length);
+
+               /* Capability length check. */
+               if ((pnt + hdr->length + 3) > end) {
+                       zlog_info("%s Capability length error", peer->host);
+                       bgp_notify_send(peer, BGP_NOTIFY_CEASE, 0);
+                       return -1;
+               }
+
+               /* Fetch structure to the byte stream. */
+               memcpy(&mpc, pnt + 3, sizeof(struct capability_mp_data));
+
+               /* We know MP Capability Code. */
+               if (hdr->code == CAPABILITY_CODE_MP) {
+                       pkt_afi = ntohs(mpc.afi);
+                       pkt_safi = mpc.safi;
+
+                       /* Ignore capability when override-capability is set. */
+                       if (CHECK_FLAG(peer->flags,
+                                      PEER_FLAG_OVERRIDE_CAPABILITY))
+                               continue;
+
+                       /* Convert AFI, SAFI to internal values. */
+                       if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi,
+                                                     &safi)) {
+                               if (bgp_debug_neighbor_events(peer))
+                                       zlog_debug(
+                                               "%s Dynamic Capability MP_EXT afi/safi invalid "
+                                               "(%u/%u)",
+                                               peer->host, pkt_afi, pkt_safi);
+                               continue;
+                       }
+
+                       /* Address family check.  */
+                       if (bgp_debug_neighbor_events(peer))
+                               zlog_debug(
+                                       "%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u",
+                                       peer->host,
+                                       action == CAPABILITY_ACTION_SET
+                                               ? "Advertising"
+                                               : "Removing",
+                                       pkt_afi, pkt_safi);
+
+                       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 {
+                       zlog_warn(
+                               "%s unrecognized capability code: %d - ignored",
+                               peer->host, hdr->code);
+               }
+               pnt += hdr->length + 3;
+       }
+       return 0;
 }
 
-/* Dynamic Capability is received. 
+/* Dynamic Capability is received.
  *
  * This is exported for unit-test purposes
  */
-int
-bgp_capability_receive (struct peer *peer, bgp_size_t size)
+int bgp_capability_receive(struct peer *peer, bgp_size_t size)
 {
-  u_char *pnt;
-
-  /* Fetch pointer. */
-  pnt = stream_pnt (peer->ibuf);
-
-  if (bgp_debug_neighbor_events(peer))
-    zlog_debug ("%s rcv CAPABILITY", peer->host);
-
-  /* If peer does not have the capability, send notification. */
-  if (! CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV))
-    {
-      zlog_err ("%s [Error] BGP dynamic capability is not enabled",
-               peer->host);
-      bgp_notify_send (peer,
-                      BGP_NOTIFY_HEADER_ERR,
-                      BGP_NOTIFY_HEADER_BAD_MESTYPE);
-      return -1;
-    }
-
-  /* Status must be Established. */
-  if (peer->status != Established)
-    {
-      zlog_err ("%s [Error] Dynamic capability packet received under status %s",
-                peer->host, lookup_msg(bgp_status_msg, peer->status, NULL));
-      bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
-      return -1;
-    }
-
-  /* Parse packet. */
-  return bgp_capability_msg_parse (peer, pnt, size);
+       u_char *pnt;
+
+       /* Fetch pointer. */
+       pnt = stream_pnt(peer->ibuf);
+
+       if (bgp_debug_neighbor_events(peer))
+               zlog_debug("%s rcv CAPABILITY", peer->host);
+
+       /* If peer does not have the capability, send notification. */
+       if (!CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV)) {
+               zlog_err("%s [Error] BGP dynamic capability is not enabled",
+                        peer->host);
+               bgp_notify_send(peer, BGP_NOTIFY_HEADER_ERR,
+                               BGP_NOTIFY_HEADER_BAD_MESTYPE);
+               return -1;
+       }
+
+       /* Status must be Established. */
+       if (peer->status != Established) {
+               zlog_err(
+                       "%s [Error] Dynamic capability packet received under status %s",
+                       peer->host,
+                       lookup_msg(bgp_status_msg, peer->status, NULL));
+               bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR, 0);
+               return -1;
+       }
+
+       /* Parse packet. */
+       return bgp_capability_msg_parse(peer, pnt, size);
 }
 
 /* BGP read utility function. */
-static int
-bgp_read_packet (struct peer *peer)
+static int bgp_read_packet(struct peer *peer)
 {
-  int nbytes;
-  int readsize;
+       int nbytes;
+       int readsize;
 
-  readsize = peer->packet_size - stream_get_endp (peer->ibuf);
+       readsize = peer->packet_size - stream_get_endp(peer->ibuf);
 
-  /* If size is zero then return. */
-  if (! readsize)
-    return 0;
+       /* If size is zero then return. */
+       if (!readsize)
+               return 0;
 
-  /* Read packet from fd. */
-  nbytes = stream_read_try (peer->ibuf, peer->fd, readsize);
+       /* Read packet from fd. */
+       nbytes = stream_read_try(peer->ibuf, peer->fd, readsize);
 
-  /* If read byte is smaller than zero then error occured. */
-  if (nbytes < 0) 
-    {
-      /* Transient error should retry */
-      if (nbytes == -2)
-       return -1;
+       /* If read byte is smaller than zero then error occured. */
+       if (nbytes < 0) {
+               /* Transient error should retry */
+               if (nbytes == -2)
+                       return -1;
 
-      zlog_err ("%s [Error] bgp_read_packet error: %s",
-               peer->host, safe_strerror (errno));
+               zlog_err("%s [Error] bgp_read_packet error: %s", peer->host,
+                        safe_strerror(errno));
 
-      if (peer->status == Established) 
-       {
-         if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
-           {
-             peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
-             SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
-           }
-         else
-           peer->last_reset = PEER_DOWN_CLOSE_SESSION;
-       }
+               if (peer->status == Established) {
+                       if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_MODE)) {
+                               peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
+                               SET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
+                       } else
+                               peer->last_reset = PEER_DOWN_CLOSE_SESSION;
+               }
 
-      BGP_EVENT_ADD (peer, TCP_fatal_error);
-      return -1;
-    }  
+               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_neighbor_events(peer))
-       zlog_debug ("%s [Event] BGP connection closed fd %d",
-                   peer->host, peer->fd);
+       /* When read byte is zero : clear bgp peer and return */
+       if (nbytes == 0) {
+               if (bgp_debug_neighbor_events(peer))
+                       zlog_debug("%s [Event] BGP connection closed fd %d",
+                                  peer->host, peer->fd);
+
+               if (peer->status == Established) {
+                       if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_MODE)) {
+                               peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
+                               SET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
+                       } else
+                               peer->last_reset = PEER_DOWN_CLOSE_SESSION;
+               }
 
-      if (peer->status == Established) 
-       {
-         if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
-           {
-             peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
-             SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
-           }
-         else
-           peer->last_reset = PEER_DOWN_CLOSE_SESSION;
+               BGP_EVENT_ADD(peer, TCP_connection_closed);
+               return -1;
        }
 
-      BGP_EVENT_ADD (peer, TCP_connection_closed);
-      return -1;
-    }
-
-  /* We read partial packet. */
-  if (stream_get_endp (peer->ibuf) != peer->packet_size)
-    return -1;
+       /* We read partial packet. */
+       if (stream_get_endp(peer->ibuf) != peer->packet_size)
+               return -1;
 
-  return 0;
+       return 0;
 }
 
 /* Marker check. */
-static int
-bgp_marker_all_one (struct stream *s, int length)
+static int bgp_marker_all_one(struct stream *s, int length)
 {
-  int i;
+       int i;
 
-  for (i = 0; i < length; i++)
-    if (s->data[i] != 0xff)
-      return 0;
+       for (i = 0; i < length; i++)
+               if (s->data[i] != 0xff)
+                       return 0;
 
-  return 1;
+       return 1;
 }
 
 /* Starting point of packet process function. */
-int
-bgp_read (struct thread *thread)
+int bgp_read(struct thread *thread)
 {
-  int ret;
-  u_char type = 0;
-  struct peer *peer;
-  bgp_size_t size;
-  char notify_data_length[2];
-  u_int32_t notify_out;
-
-  /* Yes first of all get peer pointer. */
-  peer = THREAD_ARG (thread);
-  peer->t_read = NULL;
-
-  /* Note notify_out so we can check later to see if we sent another one */
-  notify_out = peer->notify_out;
-
-  /* For non-blocking IO check. */
-  if (peer->status == Connect)
-    {
-      bgp_connect_check (peer, 1);
-      goto done;
-    }
-  else
-    {
-      if (peer->fd < 0)
-       {
-         zlog_err ("bgp_read peer's fd is negative value %d", peer->fd);
-         return -1;
+       int ret;
+       u_char type = 0;
+       struct peer *peer;
+       bgp_size_t size;
+       char notify_data_length[2];
+       u_int32_t notify_out;
+
+       /* Yes first of all get peer pointer. */
+       peer = THREAD_ARG(thread);
+       peer->t_read = NULL;
+
+       /* Note notify_out so we can check later to see if we sent another one
+        */
+       notify_out = peer->notify_out;
+
+       /* For non-blocking IO check. */
+       if (peer->status == Connect) {
+               bgp_connect_check(peer, 1);
+               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);
        }
-      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 (stream_get_endp (peer->ibuf) < 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_getp (peer->ibuf, BGP_MARKER_SIZE);
-      memcpy (notify_data_length, stream_pnt (peer->ibuf), 2);
-      size = stream_getw (peer->ibuf);
-      type = stream_getc (peer->ibuf);
-
-      /* Marker check */
-      if (((type == BGP_MSG_OPEN) || (type == BGP_MSG_KEEPALIVE))
-         && ! bgp_marker_all_one (peer->ibuf, BGP_MARKER_SIZE))
-       {
-         bgp_notify_send (peer,
-                          BGP_NOTIFY_HEADER_ERR, 
-                          BGP_NOTIFY_HEADER_NOT_SYNC);
-         goto done;
+
+       /* Read packet header to determine type of the packet */
+       if (peer->packet_size == 0)
+               peer->packet_size = BGP_HEADER_SIZE;
+
+       if (stream_get_endp(peer->ibuf) < 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_getp(peer->ibuf, BGP_MARKER_SIZE);
+               memcpy(notify_data_length, stream_pnt(peer->ibuf), 2);
+               size = stream_getw(peer->ibuf);
+               type = stream_getc(peer->ibuf);
+
+               /* Marker check */
+               if (((type == BGP_MSG_OPEN) || (type == BGP_MSG_KEEPALIVE))
+                   && !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_neighbor_events(peer))
+                               zlog_debug("%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_neighbor_events(peer))
+                               zlog_debug("%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,
+                                                 (u_char *)notify_data_length,
+                                                 2);
+                       goto done;
+               }
+
+               /* Adjust size to message length. */
+               peer->packet_size = size;
        }
 
-      /* 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_neighbor_events(peer))
-           zlog_debug ("%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;
+       ret = bgp_read_packet(peer);
+       if (ret < 0)
+               goto done;
+
+       /* Get size and type again. */
+       (void)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); /* XXX return value ignored! */
+               break;
+       case BGP_MSG_UPDATE:
+               peer->readtime = monotime(NULL);
+               bgp_update_receive(peer, size);
+               break;
+       case BGP_MSG_NOTIFY:
+               bgp_notify_receive(peer, size);
+               break;
+       case BGP_MSG_KEEPALIVE:
+               peer->readtime = monotime(NULL);
+               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;
        }
-      /* 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_neighbor_events(peer))
-           zlog_debug ("%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,
-                                    (u_char *) notify_data_length, 2);
-         goto done;
+
+       /* If reading this packet caused us to send a NOTIFICATION then store a
+        * copy
+        * of the packet for troubleshooting purposes
+        */
+       if (notify_out < peer->notify_out) {
+               memcpy(peer->last_reset_cause, peer->ibuf->data,
+                      peer->packet_size);
+               peer->last_reset_cause_size = peer->packet_size;
+               notify_out = peer->notify_out;
+       }
+
+       /* Clear input buffer. */
+       peer->packet_size = 0;
+       if (peer->ibuf)
+               stream_reset(peer->ibuf);
+
+done:
+       /* If reading this packet caused us to send a NOTIFICATION then store a
+        * copy
+        * of the packet for troubleshooting purposes
+        */
+       if (notify_out < peer->notify_out) {
+               memcpy(peer->last_reset_cause, peer->ibuf->data,
+                      peer->packet_size);
+               peer->last_reset_cause_size = peer->packet_size;
        }
 
-      /* Adjust size to message length. */
-      peer->packet_size = size;
-    }
-
-  ret = bgp_read_packet (peer);
-  if (ret < 0) 
-    goto done;
-
-  /* Get size and type again. */
-  (void)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); /* XXX return value ignored! */
-      break;
-    case BGP_MSG_UPDATE:
-      peer->readtime = monotime (NULL);
-      bgp_update_receive (peer, size);
-      break;
-    case BGP_MSG_NOTIFY:
-      bgp_notify_receive (peer, size);
-      break;
-    case BGP_MSG_KEEPALIVE:
-      peer->readtime = monotime (NULL);
-      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;
-    }
-
-  /* If reading this packet caused us to send a NOTIFICATION then store a copy
-   * of the packet for troubleshooting purposes
-   */
-  if (notify_out < peer->notify_out)
-    {
-      memcpy(peer->last_reset_cause, peer->ibuf->data, peer->packet_size);
-      peer->last_reset_cause_size = peer->packet_size;
-      notify_out = peer->notify_out;
-    }
-
-  /* Clear input buffer. */
-  peer->packet_size = 0;
-  if (peer->ibuf)
-    stream_reset (peer->ibuf);
-
- done:
-  /* If reading this packet caused us to send a NOTIFICATION then store a copy
-   * of the packet for troubleshooting purposes
-   */
-  if (notify_out < peer->notify_out)
-    {
-      memcpy(peer->last_reset_cause, peer->ibuf->data, peer->packet_size);
-      peer->last_reset_cause_size = peer->packet_size;
-    }
-
-  return 0;
+       return 0;
 }