LCOV - code coverage report
Current view: top level - bgpd - bgp_packet.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 105 1086 9.7 %
Date: 2015-11-19 Functions: 8 32 25.0 %

          Line data    Source code
       1             : /* BGP packet management routine.
       2             :    Copyright (C) 1999 Kunihiro Ishiguro
       3             : 
       4             : This file is part of GNU Zebra.
       5             : 
       6             : GNU Zebra is free software; you can redistribute it and/or modify it
       7             : under the terms of the GNU General Public License as published by the
       8             : Free Software Foundation; either version 2, or (at your option) any
       9             : later version.
      10             : 
      11             : GNU Zebra is distributed in the hope that it will be useful, but
      12             : WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             : General Public License for more details.
      15             : 
      16             : You should have received a copy of the GNU General Public License
      17             : along with GNU Zebra; see the file COPYING.  If not, write to the Free
      18             : Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
      19             : 02111-1307, USA.  */
      20             : 
      21             : #include <zebra.h>
      22             : 
      23             : #include "thread.h"
      24             : #include "stream.h"
      25             : #include "network.h"
      26             : #include "prefix.h"
      27             : #include "command.h"
      28             : #include "log.h"
      29             : #include "memory.h"
      30             : #include "sockunion.h"                /* for inet_ntop () */
      31             : #include "linklist.h"
      32             : #include "plist.h"
      33             : 
      34             : #include "bgpd/bgpd.h"
      35             : #include "bgpd/bgp_table.h"
      36             : #include "bgpd/bgp_dump.h"
      37             : #include "bgpd/bgp_attr.h"
      38             : #include "bgpd/bgp_debug.h"
      39             : #include "bgpd/bgp_fsm.h"
      40             : #include "bgpd/bgp_route.h"
      41             : #include "bgpd/bgp_packet.h"
      42             : #include "bgpd/bgp_open.h"
      43             : #include "bgpd/bgp_aspath.h"
      44             : #include "bgpd/bgp_community.h"
      45             : #include "bgpd/bgp_ecommunity.h"
      46             : #include "bgpd/bgp_network.h"
      47             : #include "bgpd/bgp_mplsvpn.h"
      48             : #include "bgpd/bgp_advertise.h"
      49             : #include "bgpd/bgp_vty.h"
      50             : 
      51             : int stream_put_prefix (struct stream *, struct prefix *);
      52             : 
      53             : /* Set up BGP packet marker and packet type. */
      54             : static int
      55          34 : bgp_packet_set_marker (struct stream *s, u_char type)
      56             : {
      57             :   int i;
      58             : 
      59             :   /* Fill in marker. */
      60         578 :   for (i = 0; i < BGP_MARKER_SIZE; i++)
      61         544 :     stream_putc (s, 0xff);
      62             : 
      63             :   /* Dummy total length. This field is should be filled in later on. */
      64          34 :   stream_putw (s, 0);
      65             : 
      66             :   /* BGP packet type. */
      67          34 :   stream_putc (s, type);
      68             : 
      69             :   /* Return current stream size. */
      70          34 :   return stream_get_endp (s);
      71             : }
      72             : 
      73             : /* Set BGP packet header size entry.  If size is zero then use current
      74             :    stream size. */
      75             : static int
      76          34 : bgp_packet_set_size (struct stream *s)
      77             : {
      78             :   int cp;
      79             : 
      80             :   /* Preserve current pointer. */
      81          34 :   cp = stream_get_endp (s);
      82          34 :   stream_putw_at (s, BGP_MARKER_SIZE, cp);
      83             : 
      84          34 :   return cp;
      85             : }
      86             : 
      87             : /* Add new packet to the peer. */
      88             : static void
      89          34 : bgp_packet_add (struct peer *peer, struct stream *s)
      90             : {
      91             :   /* Add packet to the end of list. */
      92          34 :   stream_fifo_push (peer->obuf, s);
      93          34 : }
      94             : 
      95             : /* Free first packet. */
      96             : static void
      97           0 : bgp_packet_delete (struct peer *peer)
      98             : {
      99           0 :   stream_free (stream_fifo_pop (peer->obuf));
     100           0 : }
     101             : 
     102             : /* Check file descriptor whether connect is established. */
     103             : static void
     104           0 : bgp_connect_check (struct peer *peer)
     105             : {
     106             :   int status;
     107             :   socklen_t slen;
     108             :   int ret;
     109             : 
     110             :   /* Anyway I have to reset read and write thread. */
     111           0 :   BGP_READ_OFF (peer->t_read);
     112           0 :   BGP_WRITE_OFF (peer->t_write);
     113             : 
     114             :   /* Check file descriptor. */
     115           0 :   slen = sizeof (status);
     116           0 :   ret = getsockopt(peer->fd, SOL_SOCKET, SO_ERROR, (void *) &status, &slen);
     117             : 
     118             :   /* If getsockopt is fail, this is fatal error. */
     119           0 :   if (ret < 0)
     120             :     {
     121           0 :       zlog (peer->log, LOG_INFO, "can't get sockopt for nonblocking connect");
     122           0 :       BGP_EVENT_ADD (peer, TCP_fatal_error);
     123           0 :       return;
     124             :     }      
     125             : 
     126             :   /* When status is 0 then TCP connection is established. */
     127           0 :   if (status == 0)
     128             :     {
     129           0 :       BGP_EVENT_ADD (peer, TCP_connection_open);
     130             :     }
     131             :   else
     132             :     {
     133           0 :       if (BGP_DEBUG (events, EVENTS))
     134           0 :           plog_debug (peer->log, "%s [Event] Connect failed (%s)",
     135           0 :                      peer->host, safe_strerror (errno));
     136           0 :       BGP_EVENT_ADD (peer, TCP_connection_open_failed);
     137             :     }
     138             : }
     139             : 
     140             : /* Make BGP update packet.  */
     141             : static struct stream *
     142           0 : bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
     143             : {
     144             :   struct stream *s;
     145             :   struct bgp_adj_out *adj;
     146             :   struct bgp_advertise *adv;
     147             :   struct stream *packet;
     148           0 :   struct bgp_node *rn = NULL;
     149           0 :   struct bgp_info *binfo = NULL;
     150           0 :   bgp_size_t total_attr_len = 0;
     151             :   unsigned long pos;
     152             : 
     153           0 :   s = peer->work;
     154           0 :   stream_reset (s);
     155             : 
     156           0 :   adv = FIFO_HEAD (&peer->sync[afi][safi]->update);
     157             : 
     158           0 :   while (adv)
     159             :     {
     160           0 :       assert (adv->rn);
     161           0 :       rn = adv->rn;
     162           0 :       adj = adv->adj;
     163           0 :       if (adv->binfo)
     164           0 :         binfo = adv->binfo;
     165             : 
     166             :       /* When remaining space can't include NLRI and it's length.  */
     167           0 :       if (STREAM_REMAIN (s) <= BGP_NLRI_LENGTH + PSIZE (rn->p.prefixlen))
     168           0 :         break;
     169             : 
     170             :       /* If packet is empty, set attribute. */
     171           0 :       if (stream_empty (s))
     172             :         {
     173           0 :           struct prefix_rd *prd = NULL;
     174           0 :           u_char *tag = NULL;
     175           0 :           struct peer *from = NULL;
     176             :           
     177           0 :           if (rn->prn)
     178           0 :             prd = (struct prefix_rd *) &rn->prn->p;
     179           0 :           if (binfo)
     180             :             {
     181           0 :               from = binfo->peer;
     182           0 :               if (binfo->extra)
     183           0 :                 tag = binfo->extra->tag;
     184             :             }
     185             :           
     186           0 :           bgp_packet_set_marker (s, BGP_MSG_UPDATE);
     187           0 :           stream_putw (s, 0);           
     188           0 :           pos = stream_get_endp (s);
     189           0 :           stream_putw (s, 0);
     190           0 :           total_attr_len = bgp_packet_attribute (NULL, peer, s, 
     191           0 :                                                  adv->baa->attr,
     192             :                                                  &rn->p, afi, safi, 
     193             :                                                  from, prd, tag);
     194           0 :           stream_putw_at (s, pos, total_attr_len);
     195             :         }
     196             : 
     197           0 :       if (afi == AFI_IP && safi == SAFI_UNICAST)
     198           0 :         stream_put_prefix (s, &rn->p);
     199             :       
     200           0 :       if (BGP_DEBUG (update, UPDATE_OUT))
     201             :         {
     202             :           char buf[INET6_BUFSIZ];
     203             : 
     204           0 :           zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d",
     205             :                 peer->host,
     206           0 :                 inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
     207           0 :                 rn->p.prefixlen);
     208             :         }
     209             : 
     210             :       /* Synchnorize attribute.  */
     211           0 :       if (adj->attr)
     212           0 :         bgp_attr_unintern (&adj->attr);
     213             :       else
     214           0 :         peer->scount[afi][safi]++;
     215             : 
     216           0 :       adj->attr = bgp_attr_intern (adv->baa->attr);
     217             : 
     218           0 :       adv = bgp_advertise_clean (peer, adj, afi, safi);
     219             : 
     220           0 :       if (! (afi == AFI_IP && safi == SAFI_UNICAST))
     221             :         break;
     222             :     }
     223             :          
     224           0 :   if (! stream_empty (s))
     225             :     {
     226           0 :       bgp_packet_set_size (s);
     227           0 :       packet = stream_dup (s);
     228           0 :       bgp_packet_add (peer, packet);
     229           0 :       BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
     230           0 :       stream_reset (s);
     231           0 :       return packet;
     232             :     }
     233           0 :   return NULL;
     234             : }
     235             : 
     236             : static struct stream *
     237           0 : bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi)
     238             : {
     239             :   struct stream *s;
     240             :   struct stream *packet;
     241             : 
     242             :   if (DISABLE_BGP_ANNOUNCE)
     243             :     return NULL;
     244             : 
     245           0 :   if (BGP_DEBUG (normal, NORMAL))
     246           0 :     zlog_debug ("send End-of-RIB for %s to %s", afi_safi_print (afi, safi), peer->host);
     247             : 
     248           0 :   s = stream_new (BGP_MAX_PACKET_SIZE);
     249             : 
     250             :   /* Make BGP update packet. */
     251           0 :   bgp_packet_set_marker (s, BGP_MSG_UPDATE);
     252             : 
     253             :   /* Unfeasible Routes Length */
     254           0 :   stream_putw (s, 0);
     255             : 
     256           0 :   if (afi == AFI_IP && safi == SAFI_UNICAST)
     257             :     {
     258             :       /* Total Path Attribute Length */
     259           0 :       stream_putw (s, 0);
     260             :     }
     261             :   else
     262             :     {
     263             :       /* Total Path Attribute Length */
     264           0 :       stream_putw (s, 6);
     265           0 :       stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
     266           0 :       stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
     267           0 :       stream_putc (s, 3);
     268           0 :       stream_putw (s, afi);
     269           0 :       stream_putc (s, safi);
     270             :     }
     271             : 
     272           0 :   bgp_packet_set_size (s);
     273           0 :   packet = stream_dup (s);
     274           0 :   bgp_packet_add (peer, packet);
     275           0 :   stream_free (s);
     276           0 :   return packet;
     277             : }
     278             : 
     279             : /* Make BGP withdraw packet.  */
     280             : static struct stream *
     281           0 : bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
     282             : {
     283             :   struct stream *s;
     284             :   struct stream *packet;
     285             :   struct bgp_adj_out *adj;
     286             :   struct bgp_advertise *adv;
     287             :   struct bgp_node *rn;
     288             :   unsigned long pos;
     289             :   bgp_size_t unfeasible_len;
     290             :   bgp_size_t total_attr_len;
     291             : 
     292           0 :   s = peer->work;
     293           0 :   stream_reset (s);
     294             : 
     295           0 :   while ((adv = FIFO_HEAD (&peer->sync[afi][safi]->withdraw)) != NULL)
     296             :     {
     297           0 :       assert (adv->rn);
     298           0 :       adj = adv->adj;
     299           0 :       rn = adv->rn;
     300             : 
     301           0 :       if (STREAM_REMAIN (s) 
     302           0 :           < (BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN + PSIZE (rn->p.prefixlen)))
     303           0 :         break;
     304             : 
     305           0 :       if (stream_empty (s))
     306             :         {
     307           0 :           bgp_packet_set_marker (s, BGP_MSG_UPDATE);
     308           0 :           stream_putw (s, 0);
     309             :         }
     310             : 
     311           0 :       if (afi == AFI_IP && safi == SAFI_UNICAST)
     312           0 :         stream_put_prefix (s, &rn->p);
     313             :       else
     314             :         {
     315           0 :           struct prefix_rd *prd = NULL;
     316             :           
     317           0 :           if (rn->prn)
     318           0 :             prd = (struct prefix_rd *) &rn->prn->p;
     319           0 :           pos = stream_get_endp (s);
     320           0 :           stream_putw (s, 0);
     321             :           total_attr_len
     322           0 :             = bgp_packet_withdraw (peer, s, &rn->p, afi, safi, prd, NULL);
     323             :       
     324             :           /* Set total path attribute length. */
     325           0 :           stream_putw_at (s, pos, total_attr_len);
     326             :         }
     327             : 
     328           0 :       if (BGP_DEBUG (update, UPDATE_OUT))
     329             :         {
     330             :           char buf[INET6_BUFSIZ];
     331             : 
     332           0 :           zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable",
     333             :                 peer->host,
     334           0 :                 inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
     335           0 :                 rn->p.prefixlen);
     336             :         }
     337             : 
     338           0 :       peer->scount[afi][safi]--;
     339             : 
     340           0 :       bgp_adj_out_remove (rn, adj, peer, afi, safi);
     341           0 :       bgp_unlock_node (rn);
     342             : 
     343           0 :       if (! (afi == AFI_IP && safi == SAFI_UNICAST))
     344             :         break;
     345             :     }
     346             : 
     347           0 :   if (! stream_empty (s))
     348             :     {
     349           0 :       if (afi == AFI_IP && safi == SAFI_UNICAST)
     350             :         {
     351             :           unfeasible_len 
     352           0 :             = stream_get_endp (s) - BGP_HEADER_SIZE - BGP_UNFEASIBLE_LEN;
     353           0 :           stream_putw_at (s, BGP_HEADER_SIZE, unfeasible_len);
     354           0 :           stream_putw (s, 0);
     355             :         }
     356           0 :       bgp_packet_set_size (s);
     357           0 :       packet = stream_dup (s);
     358           0 :       bgp_packet_add (peer, packet);
     359           0 :       stream_reset (s);
     360           0 :       return packet;
     361             :     }
     362             : 
     363           0 :   return NULL;
     364             : }
     365             : 
     366             : void
     367           0 : bgp_default_update_send (struct peer *peer, struct attr *attr,
     368             :                          afi_t afi, safi_t safi, struct peer *from)
     369             : {
     370             :   struct stream *s;
     371             :   struct stream *packet;
     372             :   struct prefix p;
     373             :   unsigned long pos;
     374             :   bgp_size_t total_attr_len;
     375             : 
     376             :   if (DISABLE_BGP_ANNOUNCE)
     377             :     return;
     378             : 
     379           0 :   if (afi == AFI_IP)
     380           0 :     str2prefix ("0.0.0.0/0", &p);
     381             : #ifdef HAVE_IPV6
     382             :   else 
     383           0 :     str2prefix ("::/0", &p);
     384             : #endif /* HAVE_IPV6 */
     385             : 
     386             :   /* Logging the attribute. */
     387           0 :   if (BGP_DEBUG (update, UPDATE_OUT))
     388             :     {
     389             :       char attrstr[BUFSIZ];
     390             :       char buf[INET6_BUFSIZ];
     391           0 :       attrstr[0] = '\0';
     392             : 
     393           0 :       bgp_dump_attr (peer, attr, attrstr, BUFSIZ);
     394           0 :       zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d %s",
     395           0 :             peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
     396           0 :             p.prefixlen, attrstr);
     397             :     }
     398             : 
     399           0 :   s = stream_new (BGP_MAX_PACKET_SIZE);
     400             : 
     401             :   /* Make BGP update packet. */
     402           0 :   bgp_packet_set_marker (s, BGP_MSG_UPDATE);
     403             : 
     404             :   /* Unfeasible Routes Length. */
     405           0 :   stream_putw (s, 0);
     406             : 
     407             :   /* Make place for total attribute length.  */
     408           0 :   pos = stream_get_endp (s);
     409           0 :   stream_putw (s, 0);
     410           0 :   total_attr_len = bgp_packet_attribute (NULL, peer, s, attr, &p, afi, safi, from, NULL, NULL);
     411             : 
     412             :   /* Set Total Path Attribute Length. */
     413           0 :   stream_putw_at (s, pos, total_attr_len);
     414             : 
     415             :   /* NLRI set. */
     416           0 :   if (p.family == AF_INET && safi == SAFI_UNICAST)
     417           0 :     stream_put_prefix (s, &p);
     418             : 
     419             :   /* Set size. */
     420           0 :   bgp_packet_set_size (s);
     421             : 
     422           0 :   packet = stream_dup (s);
     423           0 :   stream_free (s);
     424             : 
     425             :   /* Dump packet if debug option is set. */
     426             : #ifdef DEBUG
     427             :   /* bgp_packet_dump (packet); */
     428             : #endif /* DEBUG */
     429             : 
     430             :   /* Add packet to the peer. */
     431           0 :   bgp_packet_add (peer, packet);
     432             : 
     433           0 :   BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
     434             : }
     435             : 
     436             : void
     437           0 : bgp_default_withdraw_send (struct peer *peer, afi_t afi, safi_t safi)
     438             : {
     439             :   struct stream *s;
     440             :   struct stream *packet;
     441             :   struct prefix p;
     442             :   unsigned long pos;
     443             :   unsigned long cp;
     444             :   bgp_size_t unfeasible_len;
     445             :   bgp_size_t total_attr_len;
     446             : 
     447             :   if (DISABLE_BGP_ANNOUNCE)
     448             :     return;
     449             : 
     450           0 :   if (afi == AFI_IP)
     451           0 :     str2prefix ("0.0.0.0/0", &p);
     452             : #ifdef HAVE_IPV6
     453             :   else 
     454           0 :     str2prefix ("::/0", &p);
     455             : #endif /* HAVE_IPV6 */
     456             : 
     457           0 :   total_attr_len = 0;
     458           0 :   pos = 0;
     459             : 
     460           0 :   if (BGP_DEBUG (update, UPDATE_OUT))
     461             :     {
     462             :       char buf[INET6_BUFSIZ];
     463             : 
     464           0 :       zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable",
     465           0 :             peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
     466           0 :             p.prefixlen);
     467             :     }
     468             : 
     469           0 :   s = stream_new (BGP_MAX_PACKET_SIZE);
     470             : 
     471             :   /* Make BGP update packet. */
     472           0 :   bgp_packet_set_marker (s, BGP_MSG_UPDATE);
     473             : 
     474             :   /* Unfeasible Routes Length. */;
     475           0 :   cp = stream_get_endp (s);
     476           0 :   stream_putw (s, 0);
     477             : 
     478             :   /* Withdrawn Routes. */
     479           0 :   if (p.family == AF_INET && safi == SAFI_UNICAST)
     480             :     {
     481           0 :       stream_put_prefix (s, &p);
     482             : 
     483           0 :       unfeasible_len = stream_get_endp (s) - cp - 2;
     484             : 
     485             :       /* Set unfeasible len.  */
     486           0 :       stream_putw_at (s, cp, unfeasible_len);
     487             : 
     488             :       /* Set total path attribute length. */
     489           0 :       stream_putw (s, 0);
     490             :     }
     491             :   else
     492             :     {
     493           0 :       pos = stream_get_endp (s);
     494           0 :       stream_putw (s, 0);
     495           0 :       total_attr_len = bgp_packet_withdraw (peer, s, &p, afi, safi, NULL, NULL);
     496             : 
     497             :       /* Set total path attribute length. */
     498           0 :       stream_putw_at (s, pos, total_attr_len);
     499             :     }
     500             : 
     501           0 :   bgp_packet_set_size (s);
     502             : 
     503           0 :   packet = stream_dup (s);
     504           0 :   stream_free (s);
     505             : 
     506             :   /* Add packet to the peer. */
     507           0 :   bgp_packet_add (peer, packet);
     508             : 
     509           0 :   BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
     510             : }
     511             : 
     512             : /* Get next packet to be written.  */
     513             : static struct stream *
     514           0 : bgp_write_packet (struct peer *peer)
     515             : {
     516             :   afi_t afi;
     517             :   safi_t safi;
     518           0 :   struct stream *s = NULL;
     519             :   struct bgp_advertise *adv;
     520             : 
     521           0 :   s = stream_fifo_head (peer->obuf);
     522           0 :   if (s)
     523           0 :     return s;
     524             : 
     525           0 :   for (afi = AFI_IP; afi < AFI_MAX; afi++)
     526           0 :     for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
     527             :       {
     528           0 :         adv = FIFO_HEAD (&peer->sync[afi][safi]->withdraw);
     529           0 :         if (adv)
     530             :           {
     531           0 :             s = bgp_withdraw_packet (peer, afi, safi);
     532           0 :             if (s)
     533           0 :               return s;
     534             :           }
     535             :       }
     536             :     
     537           0 :   for (afi = AFI_IP; afi < AFI_MAX; afi++)
     538           0 :     for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
     539             :       {
     540           0 :         adv = FIFO_HEAD (&peer->sync[afi][safi]->update);
     541           0 :         if (adv)
     542             :           {
     543           0 :             if (adv->binfo && adv->binfo->uptime < peer->synctime)
     544             :               {
     545           0 :                 if (CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_RCV)
     546           0 :                     && CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_ADV)
     547           0 :                     && ! CHECK_FLAG (adv->binfo->flags, BGP_INFO_STALE)
     548           0 :                     && safi != SAFI_MPLS_VPN)
     549             :                   {
     550           0 :                     if (CHECK_FLAG (adv->binfo->peer->af_sflags[afi][safi],
     551             :                         PEER_STATUS_EOR_RECEIVED))
     552           0 :                       s = bgp_update_packet (peer, afi, safi);
     553             :                   }
     554             :                 else
     555           0 :                   s = bgp_update_packet (peer, afi, safi);
     556             :               }
     557             : 
     558           0 :             if (s)
     559           0 :               return s;
     560             :           }
     561             : 
     562           0 :         if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV))
     563             :           {
     564           0 :             if (peer->afc_nego[afi][safi] && peer->synctime
     565           0 :                 && ! CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND)
     566           0 :                 && safi != SAFI_MPLS_VPN)
     567             :               {
     568           0 :                 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND);
     569           0 :                 return bgp_update_packet_eor (peer, afi, safi);
     570             :               }
     571             :           }
     572             :       }
     573             : 
     574           0 :   return NULL;
     575             : }
     576             : 
     577             : /* Is there partially written packet or updates we can send right
     578             :    now.  */
     579             : static int
     580           0 : bgp_write_proceed (struct peer *peer)
     581             : {
     582             :   afi_t afi;
     583             :   safi_t safi;
     584             :   struct bgp_advertise *adv;
     585             : 
     586           0 :   if (stream_fifo_head (peer->obuf))
     587           0 :     return 1;
     588             : 
     589           0 :   for (afi = AFI_IP; afi < AFI_MAX; afi++)
     590           0 :     for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
     591           0 :       if (FIFO_HEAD (&peer->sync[afi][safi]->withdraw))
     592           0 :         return 1;
     593             : 
     594           0 :   for (afi = AFI_IP; afi < AFI_MAX; afi++)
     595           0 :     for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
     596           0 :       if ((adv = FIFO_HEAD (&peer->sync[afi][safi]->update)) != NULL)
     597           0 :         if (adv->binfo->uptime < peer->synctime)
     598           0 :           return 1;
     599             : 
     600           0 :   return 0;
     601             : }
     602             : 
     603             : /* Write packet to the peer. */
     604             : int
     605           0 : bgp_write (struct thread *thread)
     606             : {
     607             :   struct peer *peer;
     608             :   u_char type;
     609             :   struct stream *s; 
     610             :   int num;
     611           0 :   unsigned int count = 0;
     612             : 
     613             :   /* Yes first of all get peer pointer. */
     614           0 :   peer = THREAD_ARG (thread);
     615           0 :   peer->t_write = NULL;
     616             : 
     617             :   /* For non-blocking IO check. */
     618           0 :   if (peer->status == Connect)
     619             :     {
     620           0 :       bgp_connect_check (peer);
     621           0 :       return 0;
     622             :     }
     623             : 
     624           0 :   s = bgp_write_packet (peer);
     625           0 :   if (!s)
     626           0 :     return 0;   /* nothing to send */
     627             : 
     628           0 :   sockopt_cork (peer->fd, 1);
     629             : 
     630             :   /* Nonblocking write until TCP output buffer is full.  */
     631             :   do
     632             :     {
     633             :       int writenum;
     634             : 
     635             :       /* Number of bytes to be sent.  */
     636           0 :       writenum = stream_get_endp (s) - stream_get_getp (s);
     637             : 
     638             :       /* Call write() system call.  */
     639           0 :       num = write (peer->fd, STREAM_PNT (s), writenum);
     640           0 :       if (num < 0)
     641             :         {
     642             :           /* write failed either retry needed or error */
     643           0 :           if (ERRNO_IO_RETRY(errno))
     644             :                 break;
     645             : 
     646           0 :           BGP_EVENT_ADD (peer, TCP_fatal_error);
     647           0 :           return 0;
     648             :         }
     649             : 
     650           0 :       if (num != writenum)
     651             :         {
     652             :           /* Partial write */
     653           0 :           stream_forward_getp (s, num);
     654           0 :           break;
     655             :         }
     656             : 
     657             :       /* Retrieve BGP packet type. */
     658           0 :       stream_set_getp (s, BGP_MARKER_SIZE + 2);
     659           0 :       type = stream_getc (s);
     660             : 
     661           0 :       switch (type)
     662             :         {
     663             :         case BGP_MSG_OPEN:
     664           0 :           peer->open_out++;
     665           0 :           break;
     666             :         case BGP_MSG_UPDATE:
     667           0 :           peer->update_out++;
     668           0 :           break;
     669             :         case BGP_MSG_NOTIFY:
     670           0 :           peer->notify_out++;
     671             :           /* Double start timer. */
     672           0 :           peer->v_start *= 2;
     673             : 
     674             :           /* Overflow check. */
     675           0 :           if (peer->v_start >= (60 * 2))
     676           0 :             peer->v_start = (60 * 2);
     677             : 
     678             :           /* Flush any existing events */
     679           0 :           BGP_EVENT_ADD (peer, BGP_Stop);
     680           0 :           goto done;
     681             : 
     682             :         case BGP_MSG_KEEPALIVE:
     683           0 :           peer->keepalive_out++;
     684           0 :           break;
     685             :         case BGP_MSG_ROUTE_REFRESH_NEW:
     686             :         case BGP_MSG_ROUTE_REFRESH_OLD:
     687           0 :           peer->refresh_out++;
     688           0 :           break;
     689             :         case BGP_MSG_CAPABILITY:
     690           0 :           peer->dynamic_cap_out++;
     691           0 :           break;
     692             :         }
     693             : 
     694             :       /* OK we send packet so delete it. */
     695           0 :       bgp_packet_delete (peer);
     696             :     }
     697           0 :   while (++count < BGP_WRITE_PACKET_MAX &&
     698           0 :          (s = bgp_write_packet (peer)) != NULL);
     699             :   
     700           0 :   if (bgp_write_proceed (peer))
     701           0 :     BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
     702             : 
     703             :  done:
     704           0 :   sockopt_cork (peer->fd, 0);
     705           0 :   return 0;
     706             : }
     707             : 
     708             : /* This is only for sending NOTIFICATION message to neighbor. */
     709             : static int
     710          34 : bgp_write_notify (struct peer *peer)
     711             : {
     712             :   int ret, val;
     713             :   u_char type;
     714             :   struct stream *s; 
     715             : 
     716             :   /* There should be at least one packet. */
     717          34 :   s = stream_fifo_head (peer->obuf);
     718          34 :   if (!s)
     719           0 :     return 0;
     720          34 :   assert (stream_get_endp (s) >= BGP_HEADER_SIZE);
     721             : 
     722             :   /* Stop collecting data within the socket */
     723          34 :   sockopt_cork (peer->fd, 0);
     724             : 
     725             :   /* socket is in nonblocking mode, if we can't deliver the NOTIFY, well,
     726             :    * we only care about getting a clean shutdown at this point. */
     727          34 :   ret = write (peer->fd, STREAM_DATA (s), stream_get_endp (s));
     728             : 
     729             :   /* only connection reset/close gets counted as TCP_fatal_error, failure
     730             :    * to write the entire NOTIFY doesn't get different FSM treatment */
     731          34 :   if (ret <= 0)
     732             :     {
     733          34 :       BGP_EVENT_ADD (peer, TCP_fatal_error);
     734          34 :       return 0;
     735             :     }
     736             : 
     737             :   /* Disable Nagle, make NOTIFY packet go out right away */
     738           0 :   val = 1;
     739           0 :   (void) setsockopt (peer->fd, IPPROTO_TCP, TCP_NODELAY,
     740             :                             (char *) &val, sizeof (val));
     741             : 
     742             :   /* Retrieve BGP packet type. */
     743           0 :   stream_set_getp (s, BGP_MARKER_SIZE + 2);
     744           0 :   type = stream_getc (s);
     745             : 
     746           0 :   assert (type == BGP_MSG_NOTIFY);
     747             : 
     748             :   /* Type should be notify. */
     749           0 :   peer->notify_out++;
     750             : 
     751             :   /* Double start timer. */
     752           0 :   peer->v_start *= 2;
     753             : 
     754             :   /* Overflow check. */
     755           0 :   if (peer->v_start >= (60 * 2))
     756           0 :     peer->v_start = (60 * 2);
     757             : 
     758           0 :   BGP_EVENT_ADD (peer, BGP_Stop);
     759             : 
     760           0 :   return 0;
     761             : }
     762             : 
     763             : /* Make keepalive packet and send it to the peer. */
     764             : void
     765           0 : bgp_keepalive_send (struct peer *peer)
     766             : {
     767             :   struct stream *s;
     768             :   int length;
     769             : 
     770           0 :   s = stream_new (BGP_MAX_PACKET_SIZE);
     771             : 
     772             :   /* Make keepalive packet. */
     773           0 :   bgp_packet_set_marker (s, BGP_MSG_KEEPALIVE);
     774             : 
     775             :   /* Set packet size. */
     776           0 :   length = bgp_packet_set_size (s);
     777             : 
     778             :   /* Dump packet if debug option is set. */
     779             :   /* bgp_packet_dump (s); */
     780             :  
     781           0 :   if (BGP_DEBUG (keepalive, KEEPALIVE))  
     782           0 :     zlog_debug ("%s sending KEEPALIVE", peer->host); 
     783           0 :   if (BGP_DEBUG (normal, NORMAL))
     784           0 :     zlog_debug ("%s send message type %d, length (incl. header) %d",
     785             :                peer->host, BGP_MSG_KEEPALIVE, length);
     786             : 
     787             :   /* Add packet to the peer. */
     788           0 :   bgp_packet_add (peer, s);
     789             : 
     790           0 :   BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
     791           0 : }
     792             : 
     793             : /* Make open packet and send it to the peer. */
     794             : void
     795           0 : bgp_open_send (struct peer *peer)
     796             : {
     797             :   struct stream *s;
     798             :   int length;
     799             :   u_int16_t send_holdtime;
     800             :   as_t local_as;
     801             : 
     802           0 :   if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
     803           0 :     send_holdtime = peer->holdtime;
     804             :   else
     805           0 :     send_holdtime = peer->bgp->default_holdtime;
     806             : 
     807             :   /* local-as Change */
     808           0 :   if (peer->change_local_as)
     809           0 :     local_as = peer->change_local_as; 
     810             :   else
     811           0 :     local_as = peer->local_as; 
     812             : 
     813           0 :   s = stream_new (BGP_MAX_PACKET_SIZE);
     814             : 
     815             :   /* Make open packet. */
     816           0 :   bgp_packet_set_marker (s, BGP_MSG_OPEN);
     817             : 
     818             :   /* Set open packet values. */
     819           0 :   stream_putc (s, BGP_VERSION_4);        /* BGP version */
     820           0 :   stream_putw (s, (local_as <= BGP_AS_MAX) ? (u_int16_t) local_as 
     821             :                                            : BGP_AS_TRANS);
     822           0 :   stream_putw (s, send_holdtime);        /* Hold Time */
     823           0 :   stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */
     824             : 
     825             :   /* Set capability code. */
     826           0 :   bgp_open_capability (s, peer);
     827             : 
     828             :   /* Set BGP packet length. */
     829           0 :   length = bgp_packet_set_size (s);
     830             : 
     831           0 :   if (BGP_DEBUG (normal, NORMAL))
     832           0 :     zlog_debug ("%s sending OPEN, version %d, my as %u, holdtime %d, id %s", 
     833             :                peer->host, BGP_VERSION_4, local_as,
     834             :                send_holdtime, inet_ntoa (peer->local_id));
     835             : 
     836           0 :   if (BGP_DEBUG (normal, NORMAL))
     837           0 :     zlog_debug ("%s send message type %d, length (incl. header) %d",
     838             :                peer->host, BGP_MSG_OPEN, length);
     839             : 
     840             :   /* Dump packet if debug option is set. */
     841             :   /* bgp_packet_dump (s); */
     842             : 
     843             :   /* Add packet to the peer. */
     844           0 :   bgp_packet_add (peer, s);
     845             : 
     846           0 :   BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
     847           0 : }
     848             : 
     849             : /* Send BGP notify packet with data potion. */
     850             : void
     851          34 : bgp_notify_send_with_data (struct peer *peer, u_char code, u_char sub_code,
     852             :                            u_char *data, size_t datalen)
     853             : {
     854             :   struct stream *s;
     855             :   int length;
     856             : 
     857             :   /* Allocate new stream. */
     858          34 :   s = stream_new (BGP_MAX_PACKET_SIZE);
     859             : 
     860             :   /* Make nitify packet. */
     861          34 :   bgp_packet_set_marker (s, BGP_MSG_NOTIFY);
     862             : 
     863             :   /* Set notify packet values. */
     864          34 :   stream_putc (s, code);        /* BGP notify code */
     865          34 :   stream_putc (s, sub_code);    /* BGP notify sub_code */
     866             : 
     867             :   /* If notify data is present. */
     868          34 :   if (data)
     869           2 :     stream_write (s, data, datalen);
     870             :   
     871             :   /* Set BGP packet length. */
     872          34 :   length = bgp_packet_set_size (s);
     873             :   
     874             :   /* Add packet to the peer. */
     875          34 :   stream_fifo_clean (peer->obuf);
     876          34 :   bgp_packet_add (peer, s);
     877             : 
     878             :   /* For debug */
     879             :   {
     880             :     struct bgp_notify bgp_notify;
     881          34 :     int first = 0;
     882             :     int i;
     883             :     char c[4];
     884             : 
     885          34 :     bgp_notify.code = code;
     886          34 :     bgp_notify.subcode = sub_code;
     887          34 :     bgp_notify.data = NULL;
     888          34 :     bgp_notify.length = length - BGP_MSG_NOTIFY_MIN_SIZE;
     889             :     
     890          34 :     if (bgp_notify.length)
     891             :       {
     892           2 :         bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
     893          36 :         for (i = 0; i < bgp_notify.length; i++)
     894          34 :           if (first)
     895             :             {
     896          32 :               sprintf (c, " %02x", data[i]);
     897          32 :               strcat (bgp_notify.data, c);
     898             :             }
     899             :           else
     900             :             {
     901           2 :               first = 1;
     902           2 :               sprintf (c, "%02x", data[i]);
     903           2 :               strcpy (bgp_notify.data, c);
     904             :             }
     905             :       }
     906          34 :     bgp_notify_print (peer, &bgp_notify, "sending");
     907          34 :     if (bgp_notify.data)
     908           2 :       XFREE (MTYPE_TMP, bgp_notify.data);
     909             :   }
     910             : 
     911          34 :   if (BGP_DEBUG (normal, NORMAL))
     912          21 :     zlog_debug ("%s send message type %d, length (incl. header) %d",
     913             :                peer->host, BGP_MSG_NOTIFY, length);
     914             : 
     915             :   /* peer reset cause */
     916          34 :   if (sub_code != BGP_NOTIFY_CEASE_CONFIG_CHANGE)
     917             :     {
     918          34 :       if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET)
     919             :       {
     920           2 :         peer->last_reset = PEER_DOWN_USER_RESET;
     921           2 :         zlog_info ("Notification sent to neighbor %s: User reset", peer->host);
     922             :       }
     923          32 :       else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN)
     924             :       {
     925           0 :         peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
     926           0 :         zlog_info ("Notification sent to neighbor %s: shutdown", peer->host);
     927             :       }
     928             :       else
     929             :       {
     930          32 :         peer->last_reset = PEER_DOWN_NOTIFY_SEND;
     931          32 :         zlog_info ("Notification sent to neighbor %s: type %u/%u",
     932             :                    peer->host, code, sub_code);
     933             :       }
     934             :     }
     935             :   else
     936           0 :      zlog_info ("Notification sent to neighbor %s: configuration change",
     937             :                 peer->host);
     938             : 
     939             :   /* Call immediately. */
     940          34 :   BGP_WRITE_OFF (peer->t_write);
     941             : 
     942          34 :   bgp_write_notify (peer);
     943          34 : }
     944             : 
     945             : /* Send BGP notify packet. */
     946             : void
     947          28 : bgp_notify_send (struct peer *peer, u_char code, u_char sub_code)
     948             : {
     949          28 :   bgp_notify_send_with_data (peer, code, sub_code, NULL, 0);
     950          28 : }
     951             : 
     952             : /* Send route refresh message to the peer. */
     953             : void
     954           0 : bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
     955             :                         u_char orf_type, u_char when_to_refresh, int remove)
     956             : {
     957             :   struct stream *s;
     958             :   struct stream *packet;
     959             :   int length;
     960             :   struct bgp_filter *filter;
     961           0 :   int orf_refresh = 0;
     962             : 
     963             :   if (DISABLE_BGP_ANNOUNCE)
     964             :     return;
     965             : 
     966           0 :   filter = &peer->filter[afi][safi];
     967             : 
     968             :   /* Adjust safi code. */
     969           0 :   if (safi == SAFI_MPLS_VPN)
     970           0 :     safi = SAFI_MPLS_LABELED_VPN;
     971             :   
     972           0 :   s = stream_new (BGP_MAX_PACKET_SIZE);
     973             : 
     974             :   /* Make BGP update packet. */
     975           0 :   if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
     976           0 :     bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_NEW);
     977             :   else
     978           0 :     bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_OLD);
     979             : 
     980             :   /* Encode Route Refresh message. */
     981           0 :   stream_putw (s, afi);
     982           0 :   stream_putc (s, 0);
     983           0 :   stream_putc (s, safi);
     984             :  
     985           0 :   if (orf_type == ORF_TYPE_PREFIX
     986           0 :       || orf_type == ORF_TYPE_PREFIX_OLD)
     987           0 :     if (remove || filter->plist[FILTER_IN].plist)
     988             :       {
     989             :         u_int16_t orf_len;
     990             :         unsigned long orfp;
     991             : 
     992           0 :         orf_refresh = 1; 
     993           0 :         stream_putc (s, when_to_refresh);
     994           0 :         stream_putc (s, orf_type);
     995           0 :         orfp = stream_get_endp (s);
     996           0 :         stream_putw (s, 0);
     997             : 
     998           0 :         if (remove)
     999             :           {
    1000           0 :             UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
    1001           0 :             stream_putc (s, ORF_COMMON_PART_REMOVE_ALL);
    1002           0 :             if (BGP_DEBUG (normal, NORMAL))
    1003           0 :               zlog_debug ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d", 
    1004             :                          peer->host, orf_type,
    1005             :                          (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
    1006             :                          afi, safi);
    1007             :           }
    1008             :         else
    1009             :           {
    1010           0 :             SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
    1011           0 :             prefix_bgp_orf_entry (s, filter->plist[FILTER_IN].plist,
    1012             :                                   ORF_COMMON_PART_ADD, ORF_COMMON_PART_PERMIT,
    1013             :                                   ORF_COMMON_PART_DENY);
    1014           0 :             if (BGP_DEBUG (normal, NORMAL))
    1015           0 :               zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d", 
    1016             :                          peer->host, orf_type,
    1017             :                          (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
    1018             :                          afi, safi);
    1019             :           }
    1020             : 
    1021             :         /* Total ORF Entry Len. */
    1022           0 :         orf_len = stream_get_endp (s) - orfp - 2;
    1023           0 :         stream_putw_at (s, orfp, orf_len);
    1024             :       }
    1025             : 
    1026             :   /* Set packet size. */
    1027           0 :   length = bgp_packet_set_size (s);
    1028             : 
    1029           0 :   if (BGP_DEBUG (normal, NORMAL))
    1030             :     {
    1031           0 :       if (! orf_refresh)
    1032           0 :         zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d", 
    1033             :                    peer->host, afi, safi);
    1034           0 :       zlog_debug ("%s send message type %d, length (incl. header) %d",
    1035           0 :                  peer->host, CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV) ?
    1036             :                  BGP_MSG_ROUTE_REFRESH_NEW : BGP_MSG_ROUTE_REFRESH_OLD, length);
    1037             :     }
    1038             : 
    1039             :   /* Make real packet. */
    1040           0 :   packet = stream_dup (s);
    1041           0 :   stream_free (s);
    1042             : 
    1043             :   /* Add packet to the peer. */
    1044           0 :   bgp_packet_add (peer, packet);
    1045             : 
    1046           0 :   BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
    1047             : }
    1048             : 
    1049             : /* Send capability message to the peer. */
    1050             : void
    1051           0 : bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
    1052             :                      int capability_code, int action)
    1053             : {
    1054             :   struct stream *s;
    1055             :   struct stream *packet;
    1056             :   int length;
    1057             : 
    1058             :   /* Adjust safi code. */
    1059           0 :   if (safi == SAFI_MPLS_VPN)
    1060           0 :     safi = SAFI_MPLS_LABELED_VPN;
    1061             : 
    1062           0 :   s = stream_new (BGP_MAX_PACKET_SIZE);
    1063             : 
    1064             :   /* Make BGP update packet. */
    1065           0 :   bgp_packet_set_marker (s, BGP_MSG_CAPABILITY);
    1066             : 
    1067             :   /* Encode MP_EXT capability. */
    1068           0 :   if (capability_code == CAPABILITY_CODE_MP)
    1069             :     {
    1070           0 :       stream_putc (s, action);
    1071           0 :       stream_putc (s, CAPABILITY_CODE_MP);
    1072           0 :       stream_putc (s, CAPABILITY_CODE_MP_LEN);
    1073           0 :       stream_putw (s, afi);
    1074           0 :       stream_putc (s, 0);
    1075           0 :       stream_putc (s, safi);
    1076             : 
    1077           0 :       if (BGP_DEBUG (normal, NORMAL))
    1078           0 :         zlog_debug ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d",
    1079             :                    peer->host, action == CAPABILITY_ACTION_SET ?
    1080             :                    "Advertising" : "Removing", afi, safi);
    1081             :     }
    1082             : 
    1083             :   /* Set packet size. */
    1084           0 :   length = bgp_packet_set_size (s);
    1085             : 
    1086             :   /* Make real packet. */
    1087           0 :   packet = stream_dup (s);
    1088           0 :   stream_free (s);
    1089             : 
    1090             :   /* Add packet to the peer. */
    1091           0 :   bgp_packet_add (peer, packet);
    1092             : 
    1093           0 :   if (BGP_DEBUG (normal, NORMAL))
    1094           0 :     zlog_debug ("%s send message type %d, length (incl. header) %d",
    1095             :                peer->host, BGP_MSG_CAPABILITY, length);
    1096             : 
    1097           0 :   BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
    1098           0 : }
    1099             : 
    1100             : /* RFC1771 6.8 Connection collision detection. */
    1101             : static int
    1102           0 : bgp_collision_detect (struct peer *new, struct in_addr remote_id)
    1103             : {
    1104             :   struct peer *peer;
    1105             :   struct listnode *node, *nnode;
    1106             :   struct bgp *bgp;
    1107             : 
    1108           0 :   bgp = bgp_get_default ();
    1109           0 :   if (! bgp)
    1110           0 :     return 0;
    1111             :   
    1112             :   /* Upon receipt of an OPEN message, the local system must examine
    1113             :      all of its connections that are in the OpenConfirm state.  A BGP
    1114             :      speaker may also examine connections in an OpenSent state if it
    1115             :      knows the BGP Identifier of the peer by means outside of the
    1116             :      protocol.  If among these connections there is a connection to a
    1117             :      remote BGP speaker whose BGP Identifier equals the one in the
    1118             :      OPEN message, then the local system performs the following
    1119             :      collision resolution procedure: */
    1120             : 
    1121           0 :   for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
    1122             :     {
    1123             :       /* Under OpenConfirm status, local peer structure already hold
    1124             :          remote router ID. */
    1125             : 
    1126           0 :       if (peer != new
    1127           0 :           && (peer->status == OpenConfirm || peer->status == OpenSent)
    1128           0 :           && sockunion_same (&peer->su, &new->su))
    1129             :         {
    1130             :           /* 1. The BGP Identifier of the local system is compared to
    1131             :              the BGP Identifier of the remote system (as specified in
    1132             :              the OPEN message). */
    1133             : 
    1134           0 :           if (ntohl (peer->local_id.s_addr) < ntohl (remote_id.s_addr))
    1135             :             {
    1136             :               /* 2. If the value of the local BGP Identifier is less
    1137             :                  than the remote one, the local system closes BGP
    1138             :                  connection that already exists (the one that is
    1139             :                  already in the OpenConfirm state), and accepts BGP
    1140             :                  connection initiated by the remote system. */
    1141             : 
    1142           0 :               if (peer->fd >= 0)
    1143           0 :                 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
    1144           0 :               return 1;
    1145             :             }
    1146             :           else
    1147             :             {
    1148             :               /* 3. Otherwise, the local system closes newly created
    1149             :                  BGP connection (the one associated with the newly
    1150             :                  received OPEN message), and continues to use the
    1151             :                  existing one (the one that is already in the
    1152             :                  OpenConfirm state). */
    1153             : 
    1154           0 :               if (new->fd >= 0)
    1155           0 :                 bgp_notify_send (new, BGP_NOTIFY_CEASE, 
    1156             :                                  BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
    1157           0 :               return -1;
    1158             :             }
    1159             :         }
    1160             :     }
    1161           0 :   return 0;
    1162             : }
    1163             : 
    1164             : static int
    1165           0 : bgp_open_receive (struct peer *peer, bgp_size_t size)
    1166             : {
    1167             :   int ret;
    1168             :   u_char version;
    1169             :   u_char optlen;
    1170             :   u_int16_t holdtime;
    1171             :   u_int16_t send_holdtime;
    1172             :   as_t remote_as;
    1173           0 :   as_t as4 = 0;
    1174             :   struct peer *realpeer;
    1175             :   struct in_addr remote_id;
    1176             :   int mp_capability;
    1177             :   u_int8_t notify_data_remote_as[2];
    1178             :   u_int8_t notify_data_remote_id[4];
    1179             : 
    1180           0 :   realpeer = NULL;
    1181             :   
    1182             :   /* Parse open packet. */
    1183           0 :   version = stream_getc (peer->ibuf);
    1184           0 :   memcpy (notify_data_remote_as, stream_pnt (peer->ibuf), 2);
    1185           0 :   remote_as  = stream_getw (peer->ibuf);
    1186           0 :   holdtime = stream_getw (peer->ibuf);
    1187           0 :   memcpy (notify_data_remote_id, stream_pnt (peer->ibuf), 4);
    1188           0 :   remote_id.s_addr = stream_get_ipv4 (peer->ibuf);
    1189             : 
    1190             :   /* Receive OPEN message log  */
    1191           0 :   if (BGP_DEBUG (normal, NORMAL))
    1192           0 :     zlog_debug ("%s rcv OPEN, version %d, remote-as (in open) %u,"
    1193             :                 " holdtime %d, id %s",
    1194             :                 peer->host, version, remote_as, holdtime,
    1195             :                 inet_ntoa (remote_id));
    1196             :   
    1197             :   /* BEGIN to read the capability here, but dont do it yet */
    1198           0 :   mp_capability = 0;
    1199           0 :   optlen = stream_getc (peer->ibuf);
    1200             :   
    1201           0 :   if (optlen != 0)
    1202             :     {
    1203             :       /* We need the as4 capability value *right now* because
    1204             :        * if it is there, we have not got the remote_as yet, and without
    1205             :        * that we do not know which peer is connecting to us now.
    1206             :        */ 
    1207           0 :       as4 = peek_for_as4_capability (peer, optlen);
    1208             :     }
    1209             :   
    1210             :   /* Just in case we have a silly peer who sends AS4 capability set to 0 */
    1211           0 :   if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) && !as4)
    1212             :     {
    1213           0 :       zlog_err ("%s bad OPEN, got AS4 capability, but AS4 set to 0",
    1214             :                 peer->host);
    1215           0 :       bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
    1216             :                        BGP_NOTIFY_OPEN_BAD_PEER_AS);
    1217           0 :       return -1;
    1218             :     }
    1219             :   
    1220           0 :   if (remote_as == BGP_AS_TRANS)
    1221             :     {
    1222             :           /* Take the AS4 from the capability.  We must have received the
    1223             :            * capability now!  Otherwise we have a asn16 peer who uses
    1224             :            * BGP_AS_TRANS, for some unknown reason.
    1225             :            */
    1226           0 :       if (as4 == BGP_AS_TRANS)
    1227             :         {
    1228           0 :           zlog_err ("%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed",
    1229             :                     peer->host);
    1230           0 :           bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
    1231             :                  BGP_NOTIFY_OPEN_BAD_PEER_AS);
    1232           0 :           return -1;
    1233             :         }
    1234             :       
    1235           0 :       if (!as4 && BGP_DEBUG (as4, AS4))
    1236           0 :         zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but no AS4."
    1237             :                     " Odd, but proceeding.", peer->host);
    1238           0 :       else if (as4 < BGP_AS_MAX && BGP_DEBUG (as4, AS4))
    1239           0 :         zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but AS4 (%u) fits "
    1240             :                     "in 2-bytes, very odd peer.", peer->host, as4);
    1241           0 :       if (as4)
    1242           0 :         remote_as = as4;
    1243             :     } 
    1244             :   else 
    1245             :     {
    1246             :       /* We may have a partner with AS4 who has an asno < BGP_AS_MAX */
    1247             :       /* If we have got the capability, peer->as4cap must match remote_as */
    1248           0 :       if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)
    1249           0 :           && as4 != remote_as)
    1250             :         {
    1251             :           /* raise error, log this, close session */
    1252           0 :           zlog_err ("%s bad OPEN, got AS4 capability, but remote_as %u"
    1253             :                     " mismatch with 16bit 'myasn' %u in open",
    1254             :                     peer->host, as4, remote_as);
    1255           0 :           bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
    1256             :                            BGP_NOTIFY_OPEN_BAD_PEER_AS);
    1257           0 :           return -1;
    1258             :         }
    1259             :     }
    1260             : 
    1261             :   /* Lookup peer from Open packet. */
    1262           0 :   if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
    1263             :     {
    1264           0 :       int as = 0;
    1265             : 
    1266           0 :       realpeer = peer_lookup_with_open (&peer->su, remote_as, &remote_id, &as);
    1267             : 
    1268           0 :       if (! realpeer)
    1269             :         {
    1270             :           /* Peer's source IP address is check in bgp_accept(), so this
    1271             :              must be AS number mismatch or remote-id configuration
    1272             :              mismatch. */
    1273           0 :           if (as)
    1274             :             {
    1275           0 :               if (BGP_DEBUG (normal, NORMAL))
    1276           0 :                 zlog_debug ("%s bad OPEN, wrong router identifier %s",
    1277             :                             peer->host, inet_ntoa (remote_id));
    1278           0 :               bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR, 
    1279             :                                          BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
    1280             :                                          notify_data_remote_id, 4);
    1281             :             }
    1282             :           else
    1283             :             {
    1284           0 :               if (BGP_DEBUG (normal, NORMAL))
    1285           0 :                 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
    1286             :                             peer->host, remote_as, peer->as);
    1287           0 :               bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
    1288             :                                          BGP_NOTIFY_OPEN_BAD_PEER_AS,
    1289             :                                          notify_data_remote_as, 2);
    1290             :             }
    1291           0 :           return -1;
    1292             :         }
    1293             :     }
    1294             : 
    1295             :   /* When collision is detected and this peer is closed.  Retrun
    1296             :      immidiately. */
    1297           0 :   ret = bgp_collision_detect (peer, remote_id);
    1298           0 :   if (ret < 0)
    1299           0 :     return ret;
    1300             : 
    1301             :   /* Hack part. */
    1302           0 :   if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
    1303             :     {
    1304           0 :         if (realpeer->status == Established
    1305           0 :             && CHECK_FLAG (realpeer->sflags, PEER_STATUS_NSF_MODE))
    1306             :         {
    1307           0 :           realpeer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
    1308           0 :           SET_FLAG (realpeer->sflags, PEER_STATUS_NSF_WAIT);
    1309             :         }
    1310           0 :         else if (ret == 0 && realpeer->status != Active
    1311           0 :                  && realpeer->status != OpenSent
    1312           0 :                  && realpeer->status != OpenConfirm
    1313           0 :                  && realpeer->status != Connect)
    1314             :         {
    1315             :           /* XXX: This is an awful problem.. 
    1316             :            *
    1317             :            * According to the RFC we should just let this connection (of the
    1318             :            * accepted 'peer') continue on to Established if the other
    1319             :            * connection (the 'realpeer' one) is in state Connect, and deal
    1320             :            * with the more larval FSM as/when it gets far enough to receive
    1321             :            * an Open. We don't do that though, we instead close the (more
    1322             :            * developed) accepted connection.
    1323             :            *
    1324             :            * This means there's a race, which if hit, can loop:
    1325             :            *
    1326             :            *       FSM for A                        FSM for B
    1327             :            *  realpeer     accept-peer       realpeer     accept-peer
    1328             :            *
    1329             :            *  Connect                        Connect
    1330             :            *               Active
    1331             :            *               OpenSent          OpenSent
    1332             :            *               <arrive here,
    1333             :            *               Notify, delete>   
    1334             :            *                                 Idle         Active
    1335             :            *   OpenSent                                   OpenSent
    1336             :            *                                              <arrive here,
    1337             :            *                                              Notify, delete>
    1338             :            *   Idle
    1339             :            *   <wait>                        <wait>
    1340             :            *   Connect                       Connect
    1341             :            *
    1342             :            *
    1343             :            * If both sides are Quagga, they're almost certain to wait for
    1344             :            * the same amount of time of course (which doesn't preclude other
    1345             :            * implementations also waiting for same time). The race is
    1346             :            * exacerbated by high-latency (in bgpd and/or the network).
    1347             :            *
    1348             :            * The reason we do this is because our FSM is tied to our peer
    1349             :            * structure, which carries our configuration information, etc. 
    1350             :            * I.e. we can't let the accepted-peer FSM continue on as it is,
    1351             :            * cause it's not associated with any actual peer configuration -
    1352             :            * it's just a dummy.
    1353             :            *
    1354             :            * It's possible we could hack-fix this by just bgp_stop'ing the
    1355             :            * realpeer and continueing on with the 'transfer FSM' below. 
    1356             :            * Ideally, we need to seperate FSMs from struct peer.
    1357             :            *
    1358             :            * Setting one side to passive avoids the race, as a workaround.
    1359             :            */
    1360           0 :           if (BGP_DEBUG (events, EVENTS))
    1361           0 :             zlog_debug ("%s peer status is %s close connection",
    1362             :                         realpeer->host, LOOKUP (bgp_status_msg,
    1363             :                         realpeer->status));
    1364           0 :           bgp_notify_send (peer, BGP_NOTIFY_CEASE,
    1365             :                            BGP_NOTIFY_CEASE_CONNECT_REJECT);
    1366             : 
    1367           0 :           return -1;
    1368             :         }
    1369             : 
    1370           0 :       if (BGP_DEBUG (events, EVENTS))
    1371           0 :         zlog_debug ("%s [Event] Transfer accept BGP peer to real (state %s)",
    1372             :                    peer->host, 
    1373             :                    LOOKUP (bgp_status_msg, realpeer->status));
    1374             : 
    1375           0 :       bgp_stop (realpeer);
    1376             :       
    1377             :       /* Transfer file descriptor. */
    1378           0 :       realpeer->fd = peer->fd;
    1379           0 :       peer->fd = -1;
    1380             : 
    1381             :       /* Transfer input buffer. */
    1382           0 :       stream_free (realpeer->ibuf);
    1383           0 :       realpeer->ibuf = peer->ibuf;
    1384           0 :       realpeer->packet_size = peer->packet_size;
    1385           0 :       peer->ibuf = NULL;
    1386             : 
    1387             :       /* Transfer status. */
    1388           0 :       realpeer->status = peer->status;
    1389           0 :       bgp_stop (peer);
    1390             :       
    1391             :       /* peer pointer change. Open packet send to neighbor. */
    1392           0 :       peer = realpeer;
    1393           0 :       bgp_open_send (peer);
    1394           0 :       if (peer->fd < 0)
    1395             :         {
    1396           0 :           zlog_err ("bgp_open_receive peer's fd is negative value %d",
    1397             :                     peer->fd);
    1398           0 :           return -1;
    1399             :         }
    1400           0 :       BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
    1401             :     }
    1402             : 
    1403             :   /* remote router-id check. */
    1404           0 :   if (remote_id.s_addr == 0
    1405           0 :       || IPV4_CLASS_DE (ntohl (remote_id.s_addr))
    1406           0 :       || ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr))
    1407             :     {
    1408           0 :       if (BGP_DEBUG (normal, NORMAL))
    1409           0 :         zlog_debug ("%s bad OPEN, wrong router identifier %s",
    1410             :                    peer->host, inet_ntoa (remote_id));
    1411           0 :       bgp_notify_send_with_data (peer, 
    1412             :                                  BGP_NOTIFY_OPEN_ERR, 
    1413             :                                  BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
    1414             :                                  notify_data_remote_id, 4);
    1415           0 :       return -1;
    1416             :     }
    1417             : 
    1418             :   /* Set remote router-id */
    1419           0 :   peer->remote_id = remote_id;
    1420             : 
    1421             :   /* Peer BGP version check. */
    1422           0 :   if (version != BGP_VERSION_4)
    1423             :     {
    1424           0 :       u_int16_t maxver = htons(BGP_VERSION_4);
    1425             :       /* XXX this reply may not be correct if version < 4  XXX */
    1426           0 :       if (BGP_DEBUG (normal, NORMAL))
    1427           0 :         zlog_debug ("%s bad protocol version, remote requested %d, local request %d",
    1428             :                    peer->host, version, BGP_VERSION_4);
    1429             :       /* Data must be in network byte order here */
    1430           0 :       bgp_notify_send_with_data (peer, 
    1431             :                                  BGP_NOTIFY_OPEN_ERR, 
    1432             :                                  BGP_NOTIFY_OPEN_UNSUP_VERSION,
    1433             :                                  (u_int8_t *) &maxver, 2);
    1434           0 :       return -1;
    1435             :     }
    1436             : 
    1437             :   /* Check neighbor as number. */
    1438           0 :   if (remote_as != peer->as)
    1439             :     {
    1440           0 :       if (BGP_DEBUG (normal, NORMAL))
    1441           0 :         zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
    1442             :                    peer->host, remote_as, peer->as);
    1443           0 :       bgp_notify_send_with_data (peer, 
    1444             :                                  BGP_NOTIFY_OPEN_ERR, 
    1445             :                                  BGP_NOTIFY_OPEN_BAD_PEER_AS,
    1446             :                                  notify_data_remote_as, 2);
    1447           0 :       return -1;
    1448             :     }
    1449             : 
    1450             :   /* From the rfc: Upon receipt of an OPEN message, a BGP speaker MUST
    1451             :      calculate the value of the Hold Timer by using the smaller of its
    1452             :      configured Hold Time and the Hold Time received in the OPEN message.
    1453             :      The Hold Time MUST be either zero or at least three seconds.  An
    1454             :      implementation may reject connections on the basis of the Hold Time. */
    1455             : 
    1456           0 :   if (holdtime < 3 && holdtime != 0)
    1457             :     {
    1458           0 :       bgp_notify_send (peer,
    1459             :                        BGP_NOTIFY_OPEN_ERR, 
    1460             :                        BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
    1461           0 :       return -1;
    1462             :     }
    1463             :     
    1464             :   /* From the rfc: A reasonable maximum time between KEEPALIVE messages
    1465             :      would be one third of the Hold Time interval.  KEEPALIVE messages
    1466             :      MUST NOT be sent more frequently than one per second.  An
    1467             :      implementation MAY adjust the rate at which it sends KEEPALIVE
    1468             :      messages as a function of the Hold Time interval. */
    1469             : 
    1470           0 :   if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
    1471           0 :     send_holdtime = peer->holdtime;
    1472             :   else
    1473           0 :     send_holdtime = peer->bgp->default_holdtime;
    1474             : 
    1475           0 :   if (holdtime < send_holdtime)
    1476           0 :     peer->v_holdtime = holdtime;
    1477             :   else
    1478           0 :     peer->v_holdtime = send_holdtime;
    1479             : 
    1480           0 :   peer->v_keepalive = peer->v_holdtime / 3;
    1481             : 
    1482             :   /* Open option part parse. */
    1483           0 :   if (optlen != 0) 
    1484             :     {
    1485           0 :       if ((ret = bgp_open_option_parse (peer, optlen, &mp_capability)) < 0)
    1486             :         {
    1487           0 :           bgp_notify_send (peer,
    1488             :                  BGP_NOTIFY_OPEN_ERR,
    1489             :                  BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
    1490           0 :           return ret;
    1491             :         }
    1492             :     }
    1493             :   else
    1494             :     {
    1495           0 :       if (BGP_DEBUG (normal, NORMAL))
    1496           0 :         zlog_debug ("%s rcvd OPEN w/ OPTION parameter len: 0",
    1497             :                    peer->host);
    1498             :     }
    1499             : 
    1500             :   /* 
    1501             :    * Assume that the peer supports the locally configured set of
    1502             :    * AFI/SAFIs if the peer did not send us any Mulitiprotocol
    1503             :    * capabilities, or if 'override-capability' is configured.
    1504             :    */
    1505           0 :   if (! mp_capability ||
    1506           0 :       CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
    1507             :     {
    1508           0 :       peer->afc_nego[AFI_IP][SAFI_UNICAST] = peer->afc[AFI_IP][SAFI_UNICAST];
    1509           0 :       peer->afc_nego[AFI_IP][SAFI_MULTICAST] = peer->afc[AFI_IP][SAFI_MULTICAST];
    1510           0 :       peer->afc_nego[AFI_IP6][SAFI_UNICAST] = peer->afc[AFI_IP6][SAFI_UNICAST];
    1511           0 :       peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = peer->afc[AFI_IP6][SAFI_MULTICAST];
    1512             :     }
    1513             : 
    1514             :   /* Get sockname. */
    1515           0 :   bgp_getsockname (peer);
    1516             : 
    1517           0 :   BGP_EVENT_ADD (peer, Receive_OPEN_message);
    1518             : 
    1519           0 :   peer->packet_size = 0;
    1520           0 :   if (peer->ibuf)
    1521           0 :     stream_reset (peer->ibuf);
    1522             : 
    1523           0 :   return 0;
    1524             : }
    1525             : 
    1526             : /* Parse BGP Update packet and make attribute object. */
    1527             : static int
    1528           0 : bgp_update_receive (struct peer *peer, bgp_size_t size)
    1529             : {
    1530             :   int ret;
    1531             :   u_char *end;
    1532             :   struct stream *s;
    1533             :   struct attr attr;
    1534             :   struct attr_extra extra;
    1535             :   bgp_size_t attribute_len;
    1536             :   bgp_size_t update_len;
    1537             :   bgp_size_t withdraw_len;
    1538             :   struct bgp_nlri update;
    1539             :   struct bgp_nlri withdraw;
    1540             :   struct bgp_nlri mp_update;
    1541             :   struct bgp_nlri mp_withdraw;
    1542             : 
    1543             :   /* Status must be Established. */
    1544           0 :   if (peer->status != Established) 
    1545             :     {
    1546           0 :       zlog_err ("%s [FSM] Update packet received under status %s",
    1547             :                 peer->host, LOOKUP (bgp_status_msg, peer->status));
    1548           0 :       bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
    1549           0 :       return -1;
    1550             :     }
    1551             : 
    1552             :   /* Set initial values. */
    1553           0 :   memset (&attr, 0, sizeof (struct attr));
    1554           0 :   memset (&extra, 0, sizeof (struct attr_extra));
    1555           0 :   memset (&update, 0, sizeof (struct bgp_nlri));
    1556           0 :   memset (&withdraw, 0, sizeof (struct bgp_nlri));
    1557           0 :   memset (&mp_update, 0, sizeof (struct bgp_nlri));
    1558           0 :   memset (&mp_withdraw, 0, sizeof (struct bgp_nlri));
    1559           0 :   attr.extra = &extra;
    1560             : 
    1561           0 :   s = peer->ibuf;
    1562           0 :   end = stream_pnt (s) + size;
    1563             : 
    1564             :   /* RFC1771 6.3 If the Unfeasible Routes Length or Total Attribute
    1565             :      Length is too large (i.e., if Unfeasible Routes Length + Total
    1566             :      Attribute Length + 23 exceeds the message Length), then the Error
    1567             :      Subcode is set to Malformed Attribute List.  */
    1568           0 :   if (stream_pnt (s) + 2 > end)
    1569             :     {
    1570           0 :       zlog_err ("%s [Error] Update packet error"
    1571             :                 " (packet length is short for unfeasible length)",
    1572             :                 peer->host);
    1573           0 :       bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, 
    1574             :                        BGP_NOTIFY_UPDATE_MAL_ATTR);
    1575           0 :       return -1;
    1576             :     }
    1577             : 
    1578             :   /* Unfeasible Route Length. */
    1579           0 :   withdraw_len = stream_getw (s);
    1580             : 
    1581             :   /* Unfeasible Route Length check. */
    1582           0 :   if (stream_pnt (s) + withdraw_len > end)
    1583             :     {
    1584           0 :       zlog_err ("%s [Error] Update packet error"
    1585             :                 " (packet unfeasible length overflow %d)",
    1586             :                 peer->host, withdraw_len);
    1587           0 :       bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, 
    1588             :                        BGP_NOTIFY_UPDATE_MAL_ATTR);
    1589           0 :       return -1;
    1590             :     }
    1591             : 
    1592             :   /* Unfeasible Route packet format check. */
    1593           0 :   if (withdraw_len > 0)
    1594             :     {
    1595           0 :       ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), withdraw_len);
    1596           0 :       if (ret < 0)
    1597           0 :         return -1;
    1598             : 
    1599           0 :       if (BGP_DEBUG (packet, PACKET_RECV))
    1600           0 :         zlog_debug ("%s [Update:RECV] Unfeasible NLRI received", peer->host);
    1601             : 
    1602           0 :       withdraw.afi = AFI_IP;
    1603           0 :       withdraw.safi = SAFI_UNICAST;
    1604           0 :       withdraw.nlri = stream_pnt (s);
    1605           0 :       withdraw.length = withdraw_len;
    1606           0 :       stream_forward_getp (s, withdraw_len);
    1607             :     }
    1608             :   
    1609             :   /* Attribute total length check. */
    1610           0 :   if (stream_pnt (s) + 2 > end)
    1611             :     {
    1612           0 :       zlog_warn ("%s [Error] Packet Error"
    1613             :                  " (update packet is short for attribute length)",
    1614             :                  peer->host);
    1615           0 :       bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, 
    1616             :                        BGP_NOTIFY_UPDATE_MAL_ATTR);
    1617           0 :       return -1;
    1618             :     }
    1619             : 
    1620             :   /* Fetch attribute total length. */
    1621           0 :   attribute_len = stream_getw (s);
    1622             : 
    1623             :   /* Attribute length check. */
    1624           0 :   if (stream_pnt (s) + attribute_len > end)
    1625             :     {
    1626           0 :       zlog_warn ("%s [Error] Packet Error"
    1627             :                  " (update packet attribute length overflow %d)",
    1628             :                  peer->host, attribute_len);
    1629           0 :       bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, 
    1630             :                        BGP_NOTIFY_UPDATE_MAL_ATTR);
    1631           0 :       return -1;
    1632             :     }
    1633             :   
    1634             :   /* Certain attribute parsing errors should not be considered bad enough
    1635             :    * to reset the session for, most particularly any partial/optional
    1636             :    * attributes that have 'tunneled' over speakers that don't understand
    1637             :    * them. Instead we withdraw only the prefix concerned.
    1638             :    * 
    1639             :    * Complicates the flow a little though..
    1640             :    */
    1641           0 :   bgp_attr_parse_ret_t attr_parse_ret = BGP_ATTR_PARSE_PROCEED;
    1642             :   /* This define morphs the update case into a withdraw when lower levels
    1643             :    * have signalled an error condition where this is best.
    1644             :    */
    1645             : #define NLRI_ATTR_ARG (attr_parse_ret != BGP_ATTR_PARSE_WITHDRAW ? &attr : NULL)
    1646             : 
    1647             :   /* Parse attribute when it exists. */
    1648           0 :   if (attribute_len)
    1649             :     {
    1650           0 :       attr_parse_ret = bgp_attr_parse (peer, &attr, attribute_len, 
    1651             :                             &mp_update, &mp_withdraw);
    1652           0 :       if (attr_parse_ret == BGP_ATTR_PARSE_ERROR)
    1653           0 :         return -1;
    1654             :     }
    1655             :   
    1656             :   /* Logging the attribute. */
    1657           0 :   if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW
    1658           0 :       || BGP_DEBUG (update, UPDATE_IN))
    1659             :     {
    1660             :       char attrstr[BUFSIZ];
    1661           0 :       attrstr[0] = '\0';
    1662             : 
    1663           0 :       ret= bgp_dump_attr (peer, &attr, attrstr, BUFSIZ);
    1664           0 :       int lvl = (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
    1665           0 :                  ? LOG_ERR : LOG_DEBUG;
    1666             :       
    1667           0 :       if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
    1668           0 :         zlog (peer->log, LOG_ERR,
    1669             :               "%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
    1670             :               peer->host);
    1671             : 
    1672           0 :       if (ret)
    1673           0 :         zlog (peer->log, lvl, "%s rcvd UPDATE w/ attr: %s",
    1674             :               peer->host, attrstr);
    1675             :     }
    1676             :   
    1677             :   /* Network Layer Reachability Information. */
    1678           0 :   update_len = end - stream_pnt (s);
    1679             : 
    1680           0 :   if (update_len)
    1681             :     {
    1682             :       /* Check NLRI packet format and prefix length. */
    1683           0 :       ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), update_len);
    1684           0 :       if (ret < 0)
    1685             :         {
    1686           0 :           bgp_attr_unintern_sub (&attr);
    1687           0 :           return -1;
    1688             :         }
    1689             : 
    1690             :       /* Set NLRI portion to structure. */
    1691           0 :       update.afi = AFI_IP;
    1692           0 :       update.safi = SAFI_UNICAST;
    1693           0 :       update.nlri = stream_pnt (s);
    1694           0 :       update.length = update_len;
    1695           0 :       stream_forward_getp (s, update_len);
    1696             :     }
    1697             : 
    1698             :   /* NLRI is processed only when the peer is configured specific
    1699             :      Address Family and Subsequent Address Family. */
    1700           0 :   if (peer->afc[AFI_IP][SAFI_UNICAST])
    1701             :     {
    1702           0 :       if (withdraw.length)
    1703           0 :         bgp_nlri_parse (peer, NULL, &withdraw);
    1704             : 
    1705           0 :       if (update.length)
    1706             :         {
    1707             :           /* We check well-known attribute only for IPv4 unicast
    1708             :              update. */
    1709           0 :           ret = bgp_attr_check (peer, &attr);
    1710           0 :           if (ret < 0)
    1711             :             {
    1712           0 :               bgp_attr_unintern_sub (&attr);
    1713           0 :               return -1;
    1714             :             }
    1715             : 
    1716           0 :           bgp_nlri_parse (peer, NLRI_ATTR_ARG, &update);
    1717             :         }
    1718             : 
    1719           0 :       if (mp_update.length
    1720           0 :           && mp_update.afi == AFI_IP 
    1721           0 :           && mp_update.safi == SAFI_UNICAST)
    1722           0 :         bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
    1723             : 
    1724           0 :       if (mp_withdraw.length
    1725           0 :           && mp_withdraw.afi == AFI_IP 
    1726           0 :           && mp_withdraw.safi == SAFI_UNICAST)
    1727           0 :         bgp_nlri_parse (peer, NULL, &mp_withdraw);
    1728             : 
    1729           0 :       if (! attribute_len && ! withdraw_len)
    1730             :         {
    1731             :           /* End-of-RIB received */
    1732           0 :           SET_FLAG (peer->af_sflags[AFI_IP][SAFI_UNICAST],
    1733             :                     PEER_STATUS_EOR_RECEIVED);
    1734             : 
    1735             :           /* NSF delete stale route */
    1736           0 :           if (peer->nsf[AFI_IP][SAFI_UNICAST])
    1737           0 :             bgp_clear_stale_route (peer, AFI_IP, SAFI_UNICAST);
    1738             : 
    1739           0 :           if (BGP_DEBUG (normal, NORMAL))
    1740           0 :             zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Unicast from %s",
    1741             :                   peer->host);
    1742             :         }
    1743             :     }
    1744           0 :   if (peer->afc[AFI_IP][SAFI_MULTICAST])
    1745             :     {
    1746           0 :       if (mp_update.length
    1747           0 :           && mp_update.afi == AFI_IP 
    1748           0 :           && mp_update.safi == SAFI_MULTICAST)
    1749           0 :         bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
    1750             : 
    1751           0 :       if (mp_withdraw.length
    1752           0 :           && mp_withdraw.afi == AFI_IP 
    1753           0 :           && mp_withdraw.safi == SAFI_MULTICAST)
    1754           0 :         bgp_nlri_parse (peer, NULL, &mp_withdraw);
    1755             : 
    1756           0 :       if (! withdraw_len
    1757           0 :           && mp_withdraw.afi == AFI_IP
    1758           0 :           && mp_withdraw.safi == SAFI_MULTICAST
    1759           0 :           && mp_withdraw.length == 0)
    1760             :         {
    1761             :           /* End-of-RIB received */
    1762           0 :           SET_FLAG (peer->af_sflags[AFI_IP][SAFI_MULTICAST],
    1763             :                     PEER_STATUS_EOR_RECEIVED);
    1764             : 
    1765             :           /* NSF delete stale route */
    1766           0 :           if (peer->nsf[AFI_IP][SAFI_MULTICAST])
    1767           0 :             bgp_clear_stale_route (peer, AFI_IP, SAFI_MULTICAST);
    1768             : 
    1769           0 :           if (BGP_DEBUG (normal, NORMAL))
    1770           0 :             zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Multicast from %s",
    1771             :                   peer->host);
    1772             :         }
    1773             :     }
    1774           0 :   if (peer->afc[AFI_IP6][SAFI_UNICAST])
    1775             :     {
    1776           0 :       if (mp_update.length 
    1777           0 :           && mp_update.afi == AFI_IP6 
    1778           0 :           && mp_update.safi == SAFI_UNICAST)
    1779           0 :         bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
    1780             : 
    1781           0 :       if (mp_withdraw.length 
    1782           0 :           && mp_withdraw.afi == AFI_IP6 
    1783           0 :           && mp_withdraw.safi == SAFI_UNICAST)
    1784           0 :         bgp_nlri_parse (peer, NULL, &mp_withdraw);
    1785             : 
    1786           0 :       if (! withdraw_len
    1787           0 :           && mp_withdraw.afi == AFI_IP6
    1788           0 :           && mp_withdraw.safi == SAFI_UNICAST
    1789           0 :           && mp_withdraw.length == 0)
    1790             :         {
    1791             :           /* End-of-RIB received */
    1792           0 :           SET_FLAG (peer->af_sflags[AFI_IP6][SAFI_UNICAST], PEER_STATUS_EOR_RECEIVED);
    1793             : 
    1794             :           /* NSF delete stale route */
    1795           0 :           if (peer->nsf[AFI_IP6][SAFI_UNICAST])
    1796           0 :             bgp_clear_stale_route (peer, AFI_IP6, SAFI_UNICAST);
    1797             : 
    1798           0 :           if (BGP_DEBUG (normal, NORMAL))
    1799           0 :             zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Unicast from %s",
    1800             :                   peer->host);
    1801             :         }
    1802             :     }
    1803           0 :   if (peer->afc[AFI_IP6][SAFI_MULTICAST])
    1804             :     {
    1805           0 :       if (mp_update.length 
    1806           0 :           && mp_update.afi == AFI_IP6 
    1807           0 :           && mp_update.safi == SAFI_MULTICAST)
    1808           0 :         bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
    1809             : 
    1810           0 :       if (mp_withdraw.length 
    1811           0 :           && mp_withdraw.afi == AFI_IP6 
    1812           0 :           && mp_withdraw.safi == SAFI_MULTICAST)
    1813           0 :         bgp_nlri_parse (peer, NULL, &mp_withdraw);
    1814             : 
    1815           0 :       if (! withdraw_len
    1816           0 :           && mp_withdraw.afi == AFI_IP6
    1817           0 :           && mp_withdraw.safi == SAFI_MULTICAST
    1818           0 :           && mp_withdraw.length == 0)
    1819             :         {
    1820             :           /* End-of-RIB received */
    1821             : 
    1822             :           /* NSF delete stale route */
    1823           0 :           if (peer->nsf[AFI_IP6][SAFI_MULTICAST])
    1824           0 :             bgp_clear_stale_route (peer, AFI_IP6, SAFI_MULTICAST);
    1825             : 
    1826           0 :           if (BGP_DEBUG (update, UPDATE_IN))
    1827           0 :             zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Multicast from %s",
    1828             :                   peer->host);
    1829             :         }
    1830             :     }
    1831           0 :   if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
    1832             :     {
    1833           0 :       if (mp_update.length 
    1834           0 :           && mp_update.afi == AFI_IP 
    1835           0 :           && mp_update.safi == SAFI_MPLS_LABELED_VPN)
    1836           0 :         bgp_nlri_parse_vpnv4 (peer, NLRI_ATTR_ARG, &mp_update);
    1837             : 
    1838           0 :       if (mp_withdraw.length 
    1839           0 :           && mp_withdraw.afi == AFI_IP 
    1840           0 :           && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN)
    1841           0 :         bgp_nlri_parse_vpnv4 (peer, NULL, &mp_withdraw);
    1842             : 
    1843           0 :       if (! withdraw_len
    1844           0 :           && mp_withdraw.afi == AFI_IP
    1845           0 :           && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN
    1846           0 :           && mp_withdraw.length == 0)
    1847             :         {
    1848             :           /* End-of-RIB received */
    1849             : 
    1850           0 :           if (BGP_DEBUG (update, UPDATE_IN))
    1851           0 :             zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for VPNv4 Unicast from %s",
    1852             :                   peer->host);
    1853             :         }
    1854             :     }
    1855             : 
    1856             :   /* Everything is done.  We unintern temporary structures which
    1857             :      interned in bgp_attr_parse(). */
    1858           0 :   bgp_attr_unintern_sub (&attr);
    1859             : 
    1860             :   /* If peering is stopped due to some reason, do not generate BGP
    1861             :      event.  */
    1862           0 :   if (peer->status != Established)
    1863           0 :     return 0;
    1864             : 
    1865             :   /* Increment packet counter. */
    1866           0 :   peer->update_in++;
    1867           0 :   peer->update_time = bgp_clock ();
    1868             : 
    1869             :   /* Rearm holdtime timer */
    1870           0 :   BGP_TIMER_OFF (peer->t_holdtime);
    1871           0 :   bgp_timer_set (peer);
    1872             : 
    1873           0 :   return 0;
    1874             : }
    1875             : 
    1876             : /* Notify message treatment function. */
    1877             : static void
    1878           0 : bgp_notify_receive (struct peer *peer, bgp_size_t size)
    1879             : {
    1880             :   struct bgp_notify bgp_notify;
    1881             : 
    1882           0 :   if (peer->notify.data)
    1883             :     {
    1884           0 :       XFREE (MTYPE_TMP, peer->notify.data);
    1885           0 :       peer->notify.data = NULL;
    1886           0 :       peer->notify.length = 0;
    1887             :     }
    1888             : 
    1889           0 :   bgp_notify.code = stream_getc (peer->ibuf);
    1890           0 :   bgp_notify.subcode = stream_getc (peer->ibuf);
    1891           0 :   bgp_notify.length = size - 2;
    1892           0 :   bgp_notify.data = NULL;
    1893             : 
    1894             :   /* Preserv notify code and sub code. */
    1895           0 :   peer->notify.code = bgp_notify.code;
    1896           0 :   peer->notify.subcode = bgp_notify.subcode;
    1897             :   /* For further diagnostic record returned Data. */
    1898           0 :   if (bgp_notify.length)
    1899             :     {
    1900           0 :       peer->notify.length = size - 2;
    1901           0 :       peer->notify.data = XMALLOC (MTYPE_TMP, size - 2);
    1902           0 :       memcpy (peer->notify.data, stream_pnt (peer->ibuf), size - 2);
    1903             :     }
    1904             : 
    1905             :   /* For debug */
    1906             :   {
    1907             :     int i;
    1908           0 :     int first = 0;
    1909             :     char c[4];
    1910             : 
    1911           0 :     if (bgp_notify.length)
    1912             :       {
    1913           0 :         bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
    1914           0 :         for (i = 0; i < bgp_notify.length; i++)
    1915           0 :           if (first)
    1916             :             {
    1917           0 :               sprintf (c, " %02x", stream_getc (peer->ibuf));
    1918           0 :               strcat (bgp_notify.data, c);
    1919             :             }
    1920             :           else
    1921             :             {
    1922           0 :               first = 1;
    1923           0 :               sprintf (c, "%02x", stream_getc (peer->ibuf));
    1924           0 :               strcpy (bgp_notify.data, c);
    1925             :             }
    1926             :       }
    1927             : 
    1928           0 :     bgp_notify_print(peer, &bgp_notify, "received");
    1929           0 :     if (bgp_notify.data)
    1930           0 :       XFREE (MTYPE_TMP, bgp_notify.data);
    1931             :   }
    1932             : 
    1933             :   /* peer count update */
    1934           0 :   peer->notify_in++;
    1935             : 
    1936           0 :   if (peer->status == Established)
    1937           0 :     peer->last_reset = PEER_DOWN_NOTIFY_RECEIVED;
    1938             : 
    1939             :   /* We have to check for Notify with Unsupported Optional Parameter.
    1940             :      in that case we fallback to open without the capability option.
    1941             :      But this done in bgp_stop. We just mark it here to avoid changing
    1942             :      the fsm tables.  */
    1943           0 :   if (bgp_notify.code == BGP_NOTIFY_OPEN_ERR &&
    1944           0 :       bgp_notify.subcode == BGP_NOTIFY_OPEN_UNSUP_PARAM )
    1945           0 :     UNSET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
    1946             : 
    1947           0 :   BGP_EVENT_ADD (peer, Receive_NOTIFICATION_message);
    1948           0 : }
    1949             : 
    1950             : /* Keepalive treatment function -- get keepalive send keepalive */
    1951             : static void
    1952           0 : bgp_keepalive_receive (struct peer *peer, bgp_size_t size)
    1953             : {
    1954           0 :   if (BGP_DEBUG (keepalive, KEEPALIVE))  
    1955           0 :     zlog_debug ("%s KEEPALIVE rcvd", peer->host); 
    1956             :   
    1957           0 :   BGP_EVENT_ADD (peer, Receive_KEEPALIVE_message);
    1958           0 : }
    1959             : 
    1960             : /* Route refresh message is received. */
    1961             : static void
    1962           0 : bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
    1963             : {
    1964             :   afi_t afi;
    1965             :   safi_t safi;
    1966             :   u_char reserved;
    1967             :   struct stream *s;
    1968             : 
    1969             :   /* If peer does not have the capability, send notification. */
    1970           0 :   if (! CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_ADV))
    1971             :     {
    1972           0 :       plog_err (peer->log, "%s [Error] BGP route refresh is not enabled",
    1973             :                 peer->host);
    1974           0 :       bgp_notify_send (peer,
    1975             :                        BGP_NOTIFY_HEADER_ERR,
    1976             :                        BGP_NOTIFY_HEADER_BAD_MESTYPE);
    1977           0 :       return;
    1978             :     }
    1979             : 
    1980             :   /* Status must be Established. */
    1981           0 :   if (peer->status != Established) 
    1982             :     {
    1983           0 :       plog_err (peer->log,
    1984             :                 "%s [Error] Route refresh packet received under status %s",
    1985             :                 peer->host, LOOKUP (bgp_status_msg, peer->status));
    1986           0 :       bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
    1987           0 :       return;
    1988             :     }
    1989             : 
    1990           0 :   s = peer->ibuf;
    1991             :   
    1992             :   /* Parse packet. */
    1993           0 :   afi = stream_getw (s);
    1994           0 :   reserved = stream_getc (s);
    1995           0 :   safi = stream_getc (s);
    1996             : 
    1997           0 :   if (BGP_DEBUG (normal, NORMAL))
    1998           0 :     zlog_debug ("%s rcvd REFRESH_REQ for afi/safi: %d/%d",
    1999             :                peer->host, afi, safi);
    2000             : 
    2001             :   /* Check AFI and SAFI. */
    2002           0 :   if ((afi != AFI_IP && afi != AFI_IP6)
    2003           0 :       || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
    2004           0 :           && safi != SAFI_MPLS_LABELED_VPN))
    2005             :     {
    2006           0 :       if (BGP_DEBUG (normal, NORMAL))
    2007             :         {
    2008           0 :           zlog_debug ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored",
    2009             :                      peer->host, afi, safi);
    2010             :         }
    2011           0 :       return;
    2012             :     }
    2013             : 
    2014             :   /* Adjust safi code. */
    2015           0 :   if (safi == SAFI_MPLS_LABELED_VPN)
    2016           0 :     safi = SAFI_MPLS_VPN;
    2017             : 
    2018           0 :   if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE)
    2019             :     {
    2020             :       u_char *end;
    2021             :       u_char when_to_refresh;
    2022             :       u_char orf_type;
    2023             :       u_int16_t orf_len;
    2024             : 
    2025           0 :       if (size - (BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) < 5)
    2026             :         {
    2027           0 :           zlog_info ("%s ORF route refresh length error", peer->host);
    2028           0 :           bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
    2029           0 :           return;
    2030             :         }
    2031             : 
    2032           0 :       when_to_refresh = stream_getc (s);
    2033           0 :       end = stream_pnt (s) + (size - 5);
    2034             : 
    2035           0 :       while ((stream_pnt (s) + 2) < end)
    2036             :         {
    2037           0 :           orf_type = stream_getc (s); 
    2038           0 :           orf_len = stream_getw (s);
    2039             :           
    2040             :           /* orf_len in bounds? */
    2041           0 :           if ((stream_pnt (s) + orf_len) > end)
    2042           0 :             break; /* XXX: Notify instead?? */
    2043           0 :           if (orf_type == ORF_TYPE_PREFIX
    2044           0 :               || orf_type == ORF_TYPE_PREFIX_OLD)
    2045             :             {
    2046           0 :               u_char *p_pnt = stream_pnt (s);
    2047           0 :               u_char *p_end = stream_pnt (s) + orf_len;
    2048             :               struct orf_prefix orfp;
    2049           0 :               u_char common = 0;
    2050             :               u_int32_t seq;
    2051             :               int psize;
    2052             :               char name[BUFSIZ];
    2053             :               int ret;
    2054             : 
    2055           0 :               if (BGP_DEBUG (normal, NORMAL))
    2056             :                 {
    2057           0 :                   zlog_debug ("%s rcvd Prefixlist ORF(%d) length %d",
    2058             :                              peer->host, orf_type, orf_len);
    2059             :                 }
    2060             : 
    2061             :               /* we're going to read at least 1 byte of common ORF header,
    2062             :                * and 7 bytes of ORF Address-filter entry from the stream
    2063             :                */
    2064           0 :               if (orf_len < 7)
    2065           0 :                 break; 
    2066             :                 
    2067             :               /* ORF prefix-list name */
    2068           0 :               sprintf (name, "%s.%d.%d", peer->host, afi, safi);
    2069             : 
    2070           0 :               while (p_pnt < p_end)
    2071             :                 {
    2072             :                   /* If the ORF entry is malformed, want to read as much of it
    2073             :                    * as possible without going beyond the bounds of the entry,
    2074             :                    * to maximise debug information.
    2075             :                    */
    2076             :                   int ok;
    2077           0 :                   memset (&orfp, 0, sizeof (struct orf_prefix));
    2078           0 :                   common = *p_pnt++;
    2079             :                   /* after ++: p_pnt <= p_end */
    2080           0 :                   if (common & ORF_COMMON_PART_REMOVE_ALL)
    2081             :                     {
    2082           0 :                       if (BGP_DEBUG (normal, NORMAL))
    2083           0 :                         zlog_debug ("%s rcvd Remove-All pfxlist ORF request", peer->host);
    2084           0 :                       prefix_bgp_orf_remove_all (name);
    2085           0 :                       break;
    2086             :                     }
    2087           0 :                   ok = ((p_end - p_pnt) >= sizeof(u_int32_t)) ;
    2088           0 :                   if (ok)
    2089             :                     {
    2090           0 :                       memcpy (&seq, p_pnt, sizeof (u_int32_t));
    2091           0 :                       p_pnt += sizeof (u_int32_t);
    2092           0 :                       orfp.seq = ntohl (seq);
    2093             :                     }
    2094             :                   else
    2095           0 :                     p_pnt = p_end ;
    2096             : 
    2097           0 :                   if ((ok = (p_pnt < p_end)))
    2098           0 :                     orfp.ge = *p_pnt++ ;      /* value checked in prefix_bgp_orf_set() */
    2099           0 :                   if ((ok = (p_pnt < p_end)))
    2100           0 :                     orfp.le = *p_pnt++ ;      /* value checked in prefix_bgp_orf_set() */
    2101           0 :                   if ((ok = (p_pnt < p_end)))
    2102           0 :                     orfp.p.prefixlen = *p_pnt++ ;
    2103           0 :                   orfp.p.family = afi2family (afi);   /* afi checked already  */
    2104             : 
    2105           0 :                   psize = PSIZE (orfp.p.prefixlen);   /* 0 if not ok          */
    2106           0 :                   if (psize > prefix_blen(&orfp.p))   /* valid for family ?   */
    2107             :                     {
    2108           0 :                       ok = 0 ;
    2109           0 :                       psize = prefix_blen(&orfp.p) ;
    2110             :                     }
    2111           0 :                   if (psize > (p_end - p_pnt))        /* valid for packet ?   */
    2112             :                     {
    2113           0 :                       ok = 0 ;
    2114           0 :                       psize = p_end - p_pnt ;
    2115             :                     }
    2116             : 
    2117           0 :                   if (psize > 0)
    2118           0 :                     memcpy (&orfp.p.u.prefix, p_pnt, psize);
    2119           0 :                   p_pnt += psize;
    2120             : 
    2121           0 :                   if (BGP_DEBUG (normal, NORMAL))
    2122             :                     {
    2123             :                       char buf[INET6_BUFSIZ];
    2124             : 
    2125           0 :                       zlog_debug ("%s rcvd %s %s seq %u %s/%d ge %d le %d%s",
    2126             :                                  peer->host,
    2127           0 :                                  (common & ORF_COMMON_PART_REMOVE ? "Remove" : "Add"),
    2128           0 :                                  (common & ORF_COMMON_PART_DENY ? "deny" : "permit"),
    2129             :                                  orfp.seq,
    2130           0 :                                  inet_ntop (orfp.p.family, &orfp.p.u.prefix, buf, INET6_BUFSIZ),
    2131           0 :                                  orfp.p.prefixlen, orfp.ge, orfp.le,
    2132             :                                  ok ? "" : " MALFORMED");
    2133             :                     }
    2134             : 
    2135           0 :                   if (ok)
    2136           0 :                     ret = prefix_bgp_orf_set (name, afi, &orfp,
    2137           0 :                                    (common & ORF_COMMON_PART_DENY ? 0 : 1 ),
    2138           0 :                                    (common & ORF_COMMON_PART_REMOVE ? 0 : 1));
    2139             : 
    2140           0 :                   if (!ok || (ret != CMD_SUCCESS))
    2141             :                     {
    2142           0 :                       if (BGP_DEBUG (normal, NORMAL))
    2143           0 :                         zlog_debug ("%s Received misformatted prefixlist ORF."
    2144             :                                     " Remove All pfxlist", peer->host);
    2145           0 :                       prefix_bgp_orf_remove_all (name);
    2146           0 :                       break;
    2147             :                     }
    2148             :                 }
    2149           0 :               peer->orf_plist[afi][safi] =
    2150           0 :                          prefix_list_lookup (AFI_ORF_PREFIX, name);
    2151             :             }
    2152           0 :           stream_forward_getp (s, orf_len);
    2153             :         }
    2154           0 :       if (BGP_DEBUG (normal, NORMAL))
    2155           0 :         zlog_debug ("%s rcvd Refresh %s ORF request", peer->host,
    2156             :                    when_to_refresh == REFRESH_DEFER ? "Defer" : "Immediate");
    2157           0 :       if (when_to_refresh == REFRESH_DEFER)
    2158           0 :         return;
    2159             :     }
    2160             : 
    2161             :   /* First update is deferred until ORF or ROUTE-REFRESH is received */
    2162           0 :   if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH))
    2163           0 :     UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
    2164             : 
    2165             :   /* Perform route refreshment to the peer */
    2166           0 :   bgp_announce_route (peer, afi, safi);
    2167             : }
    2168             : 
    2169             : static int
    2170           5 : bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
    2171             : {
    2172             :   u_char *end;
    2173             :   struct capability_mp_data mpc;
    2174             :   struct capability_header *hdr;
    2175             :   u_char action;
    2176             :   struct bgp *bgp;
    2177             :   afi_t afi;
    2178             :   safi_t safi;
    2179             : 
    2180           5 :   bgp = peer->bgp;
    2181           5 :   end = pnt + length;
    2182             : 
    2183          14 :   while (pnt < end)
    2184             :     {      
    2185             :       /* We need at least action, capability code and capability length. */
    2186           7 :       if (pnt + 3 > end)
    2187             :         {
    2188           2 :           zlog_info ("%s Capability length error", peer->host);
    2189           2 :           bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
    2190           2 :           return -1;
    2191             :         }
    2192           5 :       action = *pnt;
    2193           5 :       hdr = (struct capability_header *)(pnt + 1);
    2194             :       
    2195             :       /* Action value check.  */
    2196           5 :       if (action != CAPABILITY_ACTION_SET
    2197           0 :           && action != CAPABILITY_ACTION_UNSET)
    2198             :         {
    2199           0 :           zlog_info ("%s Capability Action Value error %d",
    2200             :                      peer->host, action);
    2201           0 :           bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
    2202           0 :           return -1;
    2203             :         }
    2204             : 
    2205           5 :       if (BGP_DEBUG (normal, NORMAL))
    2206          10 :         zlog_debug ("%s CAPABILITY has action: %d, code: %u, length %u",
    2207          10 :                    peer->host, action, hdr->code, hdr->length);
    2208             : 
    2209             :       /* Capability length check. */
    2210           5 :       if ((pnt + hdr->length + 3) > end)
    2211             :         {
    2212           1 :           zlog_info ("%s Capability length error", peer->host);
    2213           1 :           bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
    2214           1 :           return -1;
    2215             :         }
    2216             : 
    2217             :       /* Fetch structure to the byte stream. */
    2218           4 :       memcpy (&mpc, pnt + 3, sizeof (struct capability_mp_data));
    2219             : 
    2220             :       /* We know MP Capability Code. */
    2221           4 :       if (hdr->code == CAPABILITY_CODE_MP)
    2222             :         {
    2223           4 :           afi = ntohs (mpc.afi);
    2224           4 :           safi = mpc.safi;
    2225             : 
    2226             :           /* Ignore capability when override-capability is set. */
    2227           4 :           if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
    2228           0 :             continue;
    2229             :           
    2230           4 :           if (!bgp_afi_safi_valid_indices (afi, &safi))
    2231             :             {
    2232           0 :               if (BGP_DEBUG (normal, NORMAL))
    2233           0 :                 zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid "
    2234             :                             "(%u/%u)", peer->host, afi, safi);
    2235           0 :               continue;
    2236             :             }
    2237             :           
    2238             :           /* Address family check.  */
    2239           4 :           if (BGP_DEBUG (normal, NORMAL))
    2240           8 :             zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u",
    2241             :                        peer->host,
    2242             :                        action == CAPABILITY_ACTION_SET 
    2243             :                        ? "Advertising" : "Removing",
    2244           8 :                        ntohs(mpc.afi) , mpc.safi);
    2245             :               
    2246           4 :           if (action == CAPABILITY_ACTION_SET)
    2247             :             {
    2248           4 :               peer->afc_recv[afi][safi] = 1;
    2249           4 :               if (peer->afc[afi][safi])
    2250             :                 {
    2251           4 :                   peer->afc_nego[afi][safi] = 1;
    2252           4 :                   bgp_announce_route (peer, afi, safi);
    2253             :                 }
    2254             :             }
    2255             :           else
    2256             :             {
    2257           0 :               peer->afc_recv[afi][safi] = 0;
    2258           0 :               peer->afc_nego[afi][safi] = 0;
    2259             : 
    2260           0 :               if (peer_active_nego (peer))
    2261           0 :                 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
    2262             :               else
    2263           0 :                 BGP_EVENT_ADD (peer, BGP_Stop);
    2264             :             }
    2265             :         }
    2266             :       else
    2267             :         {
    2268           0 :           zlog_warn ("%s unrecognized capability code: %d - ignored",
    2269           0 :                      peer->host, hdr->code);
    2270             :         }
    2271           4 :       pnt += hdr->length + 3;
    2272             :     }
    2273           2 :   return 0;
    2274             : }
    2275             : 
    2276             : /* Dynamic Capability is received. 
    2277             :  *
    2278             :  * This is exported for unit-test purposes
    2279             :  */
    2280             : int
    2281           5 : bgp_capability_receive (struct peer *peer, bgp_size_t size)
    2282             : {
    2283             :   u_char *pnt;
    2284             : 
    2285             :   /* Fetch pointer. */
    2286           5 :   pnt = stream_pnt (peer->ibuf);
    2287             : 
    2288           5 :   if (BGP_DEBUG (normal, NORMAL))
    2289           5 :     zlog_debug ("%s rcv CAPABILITY", peer->host);
    2290             : 
    2291             :   /* If peer does not have the capability, send notification. */
    2292           5 :   if (! CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV))
    2293             :     {
    2294           0 :       plog_err (peer->log, "%s [Error] BGP dynamic capability is not enabled",
    2295             :                 peer->host);
    2296           0 :       bgp_notify_send (peer,
    2297             :                        BGP_NOTIFY_HEADER_ERR,
    2298             :                        BGP_NOTIFY_HEADER_BAD_MESTYPE);
    2299           0 :       return -1;
    2300             :     }
    2301             : 
    2302             :   /* Status must be Established. */
    2303           5 :   if (peer->status != Established)
    2304             :     {
    2305           0 :       plog_err (peer->log,
    2306             :                 "%s [Error] Dynamic capability packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status));
    2307           0 :       bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
    2308           0 :       return -1;
    2309             :     }
    2310             : 
    2311             :   /* Parse packet. */
    2312           5 :   return bgp_capability_msg_parse (peer, pnt, size);
    2313             : }
    2314             : 
    2315             : /* BGP read utility function. */
    2316             : static int
    2317           0 : bgp_read_packet (struct peer *peer)
    2318             : {
    2319             :   int nbytes;
    2320             :   int readsize;
    2321             : 
    2322           0 :   readsize = peer->packet_size - stream_get_endp (peer->ibuf);
    2323             : 
    2324             :   /* If size is zero then return. */
    2325           0 :   if (! readsize)
    2326           0 :     return 0;
    2327             : 
    2328             :   /* Read packet from fd. */
    2329           0 :   nbytes = stream_read_try (peer->ibuf, peer->fd, readsize);
    2330             : 
    2331             :   /* If read byte is smaller than zero then error occured. */
    2332           0 :   if (nbytes < 0) 
    2333             :     {
    2334             :       /* Transient error should retry */
    2335           0 :       if (nbytes == -2)
    2336           0 :         return -1;
    2337             : 
    2338           0 :       plog_err (peer->log, "%s [Error] bgp_read_packet error: %s",
    2339           0 :                  peer->host, safe_strerror (errno));
    2340             : 
    2341           0 :       if (peer->status == Established) 
    2342             :         {
    2343           0 :           if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
    2344             :             {
    2345           0 :               peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
    2346           0 :               SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
    2347             :             }
    2348             :           else
    2349           0 :             peer->last_reset = PEER_DOWN_CLOSE_SESSION;
    2350             :         }
    2351             : 
    2352           0 :       BGP_EVENT_ADD (peer, TCP_fatal_error);
    2353           0 :       return -1;
    2354             :     }  
    2355             : 
    2356             :   /* When read byte is zero : clear bgp peer and return */
    2357           0 :   if (nbytes == 0) 
    2358             :     {
    2359           0 :       if (BGP_DEBUG (events, EVENTS))
    2360           0 :         plog_debug (peer->log, "%s [Event] BGP connection closed fd %d",
    2361             :                    peer->host, peer->fd);
    2362             : 
    2363           0 :       if (peer->status == Established) 
    2364             :         {
    2365           0 :           if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
    2366             :             {
    2367           0 :               peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
    2368           0 :               SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
    2369             :             }
    2370             :           else
    2371           0 :             peer->last_reset = PEER_DOWN_CLOSE_SESSION;
    2372             :         }
    2373             : 
    2374           0 :       BGP_EVENT_ADD (peer, TCP_connection_closed);
    2375           0 :       return -1;
    2376             :     }
    2377             : 
    2378             :   /* We read partial packet. */
    2379           0 :   if (stream_get_endp (peer->ibuf) != peer->packet_size)
    2380           0 :     return -1;
    2381             : 
    2382           0 :   return 0;
    2383             : }
    2384             : 
    2385             : /* Marker check. */
    2386             : static int
    2387           0 : bgp_marker_all_one (struct stream *s, int length)
    2388             : {
    2389             :   int i;
    2390             : 
    2391           0 :   for (i = 0; i < length; i++)
    2392           0 :     if (s->data[i] != 0xff)
    2393           0 :       return 0;
    2394             : 
    2395           0 :   return 1;
    2396             : }
    2397             : 
    2398             : /* Recent thread time.
    2399             :    On same clock base as bgp_clock (MONOTONIC)
    2400             :    but can be time of last context switch to bgp_read thread. */
    2401             : static time_t
    2402           0 : bgp_recent_clock (void)
    2403             : {
    2404           0 :   return recent_relative_time().tv_sec;
    2405             : }
    2406             : 
    2407             : /* Starting point of packet process function. */
    2408             : int
    2409           0 : bgp_read (struct thread *thread)
    2410             : {
    2411             :   int ret;
    2412           0 :   u_char type = 0;
    2413             :   struct peer *peer;
    2414             :   bgp_size_t size;
    2415             :   char notify_data_length[2];
    2416             : 
    2417             :   /* Yes first of all get peer pointer. */
    2418           0 :   peer = THREAD_ARG (thread);
    2419           0 :   peer->t_read = NULL;
    2420             : 
    2421             :   /* For non-blocking IO check. */
    2422           0 :   if (peer->status == Connect)
    2423             :     {
    2424           0 :       bgp_connect_check (peer);
    2425           0 :       goto done;
    2426             :     }
    2427             :   else
    2428             :     {
    2429           0 :       if (peer->fd < 0)
    2430             :         {
    2431           0 :           zlog_err ("bgp_read peer's fd is negative value %d", peer->fd);
    2432           0 :           return -1;
    2433             :         }
    2434           0 :       BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
    2435             :     }
    2436             : 
    2437             :   /* Read packet header to determine type of the packet */
    2438           0 :   if (peer->packet_size == 0)
    2439           0 :     peer->packet_size = BGP_HEADER_SIZE;
    2440             : 
    2441           0 :   if (stream_get_endp (peer->ibuf) < BGP_HEADER_SIZE)
    2442             :     {
    2443           0 :       ret = bgp_read_packet (peer);
    2444             : 
    2445             :       /* Header read error or partial read packet. */
    2446           0 :       if (ret < 0) 
    2447           0 :         goto done;
    2448             : 
    2449             :       /* Get size and type. */
    2450           0 :       stream_forward_getp (peer->ibuf, BGP_MARKER_SIZE);
    2451           0 :       memcpy (notify_data_length, stream_pnt (peer->ibuf), 2);
    2452           0 :       size = stream_getw (peer->ibuf);
    2453           0 :       type = stream_getc (peer->ibuf);
    2454             : 
    2455           0 :       if (BGP_DEBUG (normal, NORMAL) && type != 2 && type != 0)
    2456           0 :         zlog_debug ("%s rcv message type %d, length (excl. header) %d",
    2457             :                    peer->host, type, size - BGP_HEADER_SIZE);
    2458             : 
    2459             :       /* Marker check */
    2460           0 :       if (((type == BGP_MSG_OPEN) || (type == BGP_MSG_KEEPALIVE))
    2461           0 :           && ! bgp_marker_all_one (peer->ibuf, BGP_MARKER_SIZE))
    2462             :         {
    2463           0 :           bgp_notify_send (peer,
    2464             :                            BGP_NOTIFY_HEADER_ERR, 
    2465             :                            BGP_NOTIFY_HEADER_NOT_SYNC);
    2466           0 :           goto done;
    2467             :         }
    2468             : 
    2469             :       /* BGP type check. */
    2470           0 :       if (type != BGP_MSG_OPEN && type != BGP_MSG_UPDATE 
    2471           0 :           && type != BGP_MSG_NOTIFY && type != BGP_MSG_KEEPALIVE 
    2472           0 :           && type != BGP_MSG_ROUTE_REFRESH_NEW
    2473           0 :           && type != BGP_MSG_ROUTE_REFRESH_OLD
    2474           0 :           && type != BGP_MSG_CAPABILITY)
    2475             :         {
    2476           0 :           if (BGP_DEBUG (normal, NORMAL))
    2477           0 :             plog_debug (peer->log,
    2478             :                       "%s unknown message type 0x%02x",
    2479             :                       peer->host, type);
    2480           0 :           bgp_notify_send_with_data (peer,
    2481             :                                      BGP_NOTIFY_HEADER_ERR,
    2482             :                                      BGP_NOTIFY_HEADER_BAD_MESTYPE,
    2483             :                                      &type, 1);
    2484           0 :           goto done;
    2485             :         }
    2486             :       /* Mimimum packet length check. */
    2487           0 :       if ((size < BGP_HEADER_SIZE)
    2488           0 :           || (size > BGP_MAX_PACKET_SIZE)
    2489           0 :           || (type == BGP_MSG_OPEN && size < BGP_MSG_OPEN_MIN_SIZE)
    2490           0 :           || (type == BGP_MSG_UPDATE && size < BGP_MSG_UPDATE_MIN_SIZE)
    2491           0 :           || (type == BGP_MSG_NOTIFY && size < BGP_MSG_NOTIFY_MIN_SIZE)
    2492           0 :           || (type == BGP_MSG_KEEPALIVE && size != BGP_MSG_KEEPALIVE_MIN_SIZE)
    2493           0 :           || (type == BGP_MSG_ROUTE_REFRESH_NEW && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
    2494           0 :           || (type == BGP_MSG_ROUTE_REFRESH_OLD && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
    2495           0 :           || (type == BGP_MSG_CAPABILITY && size < BGP_MSG_CAPABILITY_MIN_SIZE))
    2496             :         {
    2497           0 :           if (BGP_DEBUG (normal, NORMAL))
    2498           0 :             plog_debug (peer->log,
    2499             :                       "%s bad message length - %d for %s",
    2500             :                       peer->host, size, 
    2501           0 :                       type == 128 ? "ROUTE-REFRESH" :
    2502           0 :                       bgp_type_str[(int) type]);
    2503           0 :           bgp_notify_send_with_data (peer,
    2504             :                                      BGP_NOTIFY_HEADER_ERR,
    2505             :                                      BGP_NOTIFY_HEADER_BAD_MESLEN,
    2506             :                                      (u_char *) notify_data_length, 2);
    2507           0 :           goto done;
    2508             :         }
    2509             : 
    2510             :       /* Adjust size to message length. */
    2511           0 :       peer->packet_size = size;
    2512             :     }
    2513             : 
    2514           0 :   ret = bgp_read_packet (peer);
    2515           0 :   if (ret < 0) 
    2516           0 :     goto done;
    2517             : 
    2518             :   /* Get size and type again. */
    2519           0 :   size = stream_getw_from (peer->ibuf, BGP_MARKER_SIZE);
    2520           0 :   type = stream_getc_from (peer->ibuf, BGP_MARKER_SIZE + 2);
    2521             : 
    2522             :   /* BGP packet dump function. */
    2523           0 :   bgp_dump_packet (peer, type, peer->ibuf);
    2524             :   
    2525           0 :   size = (peer->packet_size - BGP_HEADER_SIZE);
    2526             : 
    2527             :   /* Read rest of the packet and call each sort of packet routine */
    2528           0 :   switch (type) 
    2529             :     {
    2530             :     case BGP_MSG_OPEN:
    2531           0 :       peer->open_in++;
    2532           0 :       bgp_open_receive (peer, size); /* XXX return value ignored! */
    2533           0 :       break;
    2534             :     case BGP_MSG_UPDATE:
    2535           0 :       peer->readtime = bgp_recent_clock ();
    2536           0 :       bgp_update_receive (peer, size);
    2537           0 :       break;
    2538             :     case BGP_MSG_NOTIFY:
    2539           0 :       bgp_notify_receive (peer, size);
    2540           0 :       break;
    2541             :     case BGP_MSG_KEEPALIVE:
    2542           0 :       peer->readtime = bgp_recent_clock ();
    2543           0 :       bgp_keepalive_receive (peer, size);
    2544           0 :       break;
    2545             :     case BGP_MSG_ROUTE_REFRESH_NEW:
    2546             :     case BGP_MSG_ROUTE_REFRESH_OLD:
    2547           0 :       peer->refresh_in++;
    2548           0 :       bgp_route_refresh_receive (peer, size);
    2549           0 :       break;
    2550             :     case BGP_MSG_CAPABILITY:
    2551           0 :       peer->dynamic_cap_in++;
    2552           0 :       bgp_capability_receive (peer, size);
    2553           0 :       break;
    2554             :     }
    2555             : 
    2556             :   /* Clear input buffer. */
    2557           0 :   peer->packet_size = 0;
    2558           0 :   if (peer->ibuf)
    2559           0 :     stream_reset (peer->ibuf);
    2560             : 
    2561             :  done:
    2562           0 :   if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
    2563             :     {
    2564           0 :       if (BGP_DEBUG (events, EVENTS))
    2565           0 :         zlog_debug ("%s [Event] Accepting BGP peer delete", peer->host);
    2566           0 :       peer_delete (peer);
    2567             :     }
    2568           0 :   return 0;
    2569             : }

Generated by: LCOV version 1.10