Esempio n. 1
0
s_int32_t
bpn_sock_listen_uninit (struct bgp *bgp)
{
  struct bgp_listen_sock_lnode *tmp_lnode_nxt;
  struct bgp_listen_sock_lnode *tmp_lnode;
  s_int32_t ret;

  ret = 0;

  if (! bgp)
    {
      ret = -1;
      goto EXIT;
    }

  /* Release all Listen Socket Threads */
  for (tmp_lnode = bgp->listen_sock_lnode;
       tmp_lnode; tmp_lnode = tmp_lnode_nxt)
    {
      tmp_lnode_nxt = tmp_lnode->next;

      SSOCK_FD_CLOSE (&BLG, tmp_lnode->listen_sock);
      BGP_READ_OFF (&BLG, tmp_lnode->t_accept);

      XFREE (MTYPE_TMP, tmp_lnode);
    }
  bgp->listen_sock_lnode = NULL;

 EXIT:

  return ret;
}
Esempio n. 2
0
    /* Add thread to Listen Thread List */
    tmp_lnode = XCALLOC (MTYPE_TMP,
                         sizeof (struct bgp_listen_sock_lnode));
    if (! tmp_lnode)
      {
        zlog_err (&BLG, "[NETWORK] Server Sock:"
                  " Cannot allocate memory (%d) @ %s:%d",
                  sizeof (struct bgp_peer_inconn_req), __FILE__, __LINE__);

        SSOCK_FD_CLOSE (&BLG, bgp_sock);
        BGP_READ_OFF (&BLG, t_accept);

        continue;
      }

    tmp_lnode->listen_sock = bgp_sock;
    tmp_lnode->t_accept = t_accept;
    if (bgp->listen_sock_lnode)
      tmp_lnode->next = bgp->listen_sock_lnode;
    bgp->listen_sock_lnode = tmp_lnode;

  } 

  pal_sock_freeaddrinfo (ainfo_head);

  return ret;
}
#else /* HAVE_IPV6 && !NRL */
s_int32_t
bpn_sock_listen (struct bgp *bgp, u_int16_t port)
{
  struct bgp_listen_sock_lnode *tmp_lnode;
  struct thread *t_accept;
  union sockunion su;
  s_int32_t bgp_sock;
  fib_id_t fib_id;
  s_int32_t ret;

  pal_mem_set (&su, 0, sizeof (union sockunion));

  t_accept = NULL;
  ret = 0;

  if (! bgp)
    {
      zlog_err (&BLG, "[NETWORK] Server Sock: Invalid 'bgp' instance");

      ret = -1;
      goto EXIT;
    }

  fib_id = LIB_VRF_GET_FIB_ID (bgp->owning_ivrf);

  /* Specify address family. */
  su.sa.sa_family = AF_INET;

  bgp_sock = pal_sock (&BLG, su.sa.sa_family, SOCK_STREAM, 0);
  if (bgp_sock < 0)
    {
      zlog_err (&BLG, "[NETWORK] Server Sock: socket() Failed, FIB-ID %d, "
                "Err:%d-%s", fib_id, errno, pal_strerror (errno));

      ret = -1;
      goto EXIT;
    }

  pal_sock_set_reuseaddr (bgp_sock, PAL_TRUE);
  pal_sock_set_reuseport (bgp_sock, PAL_TRUE);

  /* Bind socket to FIB. */
  ret = pal_sock_set_bindtofib (bgp_sock, fib_id);
  if (ret < 0)
    {
      zlog_err (&BLG, "[NETWORK] Server Sock: bindtofib() Failed, Sock %d"
                ", FIB-ID %d, Err:%d-%s", bgp_sock, fib_id, errno,
                pal_strerror (errno));

      SSOCK_FD_CLOSE (&BLG, bgp_sock);

      /* Ignore platform error */
      ret = 0;
      goto EXIT;
    }

  ret = sockunion_bind (&BLG, bgp_sock, &su, port, NULL);
  if (ret < 0)
    {
      zlog_err (&BLG, "[NETWORK] Server Sock: bind() Failed, Err: %d-%s",
                errno, pal_strerror (errno));

      SSOCK_FD_CLOSE (&BLG, bgp_sock);

      /* Ignore platform error */
      ret = 0;
      goto EXIT;
    }

#ifdef HAVE_TCP_MD5SIG
  bgp_md5_set_server (bgp, bgp_sock);
#endif /* TCP_MD5SIG */

  ret = pal_sock_listen (bgp_sock, BGP_SOCK_LISTEN_BACKLOG);
  if (ret < 0)
    {
      zlog_err (&BLG, "[NETWORK] Server Sock: listen() Failed, Sock %d, "
                "FIB-ID %d, Err:%d-%s", bgp_sock, fib_id, errno,
                pal_strerror (errno));

      SSOCK_FD_CLOSE (&BLG, bgp_sock);

      /* Ignore platform error */
      ret = 0;
      goto EXIT;
    }

  /* Start a fresh Accept Thread */
  BGP_READ_ON (&BLG, t_accept, bgp, bpn_sock_accept, bgp_sock);

  /* Add thread to Listen Thread List */
  tmp_lnode = XCALLOC (MTYPE_TMP, sizeof (struct bgp_listen_sock_lnode));
  if (! tmp_lnode)
    {
      zlog_err (&BLG, "[NETWORK] Server Sock:"
                " Cannot allocate memory (%d) @ %s:%d",
                sizeof (struct bgp_peer_inconn_req), __FILE__, __LINE__);

      SSOCK_FD_CLOSE (&BLG, bgp_sock);
      BGP_READ_OFF (&BLG, t_accept);

      ret = -1;
      goto EXIT;
    }

  tmp_lnode->listen_sock = bgp_sock;
  tmp_lnode->t_accept = t_accept;
  if (bgp->listen_sock_lnode)
    tmp_lnode->next = bgp->listen_sock_lnode;
  bgp->listen_sock_lnode = tmp_lnode;

 EXIT:

  return ret;
}
Esempio n. 3
0
s_int32_t
bpn_sock_listen (struct bgp *bgp, u_int16_t port)
{
  struct bgp_listen_sock_lnode *tmp_lnode;
  u_int8_t port_str [SU_ADDRSTRLEN];
  struct pal_addrinfo *ainfo_save[2], *ainfo_head;
  struct pal_addrinfo *ainfo;
  struct pal_sockaddr_in4 ain4;
  struct pal_sockaddr_in6 ain6;
  struct pal_addrinfo req;
  struct thread *t_accept;
  s_int32_t bgp_sock;
  u_int8_t addr_set;
  fib_id_t fib_id;
  s_int32_t ret;	
  int i, flags = 1;

  pal_mem_set (&req, 0, sizeof (struct pal_addrinfo));
  t_accept = NULL;
  ainfo_save[0] = NULL;
  ainfo_save[1] = NULL;
  ret = 0;
  addr_set = 0;

  if (! bgp)
    {
      zlog_err (&BLG, "[NETWORK] Server Sock: Invalid 'bgp' instance");

      return -1;
    }

  fib_id = LIB_VRF_GET_FIB_ID (bgp->owning_ivrf);
  req.ai_flags = AI_PASSIVE;
  req.ai_family = AF_UNSPEC;
  req.ai_socktype = SOCK_STREAM;
  pal_snprintf (port_str, SU_ADDRSTRLEN, "%d", port);
  port_str[sizeof (port_str) - 1] = '\0';

  ret = pal_sock_getaddrinfo (NULL, port_str, &req, &ainfo);
  if (ret != 0)
    {
      zlog_err (&BLG, "[NETWORK] Server Sock: getaddrinfo() failed: %d-%s",
                errno, pal_strerror (errno));

      return ret;
    }

  ainfo_head = ainfo;
  /* IPv4 can connect to IPv6 socket, not other way around. */
  while (ainfo)
    {
      if (ainfo->ai_family == AF_INET)
        ainfo_save[1] = ainfo;
      else if (ainfo->ai_family == AF_INET6)
        ainfo_save[0] = ainfo;

      ainfo = ainfo->ai_next;
    }

  for (i = 0; i < 2; i++) {
    ainfo = ainfo_save[i];

    if (! ainfo)
      continue;

    if (ainfo->ai_family != AF_INET && ainfo->ai_family != AF_INET6)
      continue;

    bgp_sock = pal_sock (&BLG, ainfo->ai_family, ainfo->ai_socktype,
                         ainfo->ai_protocol);
    if (bgp_sock < 0)
      {
        zlog_err (&BLG, "[NETWORK] Server Sock: socket() Failed for AF"
                  "=%d, FIB-ID %d, Err:%d-%s", ainfo->ai_family,
                  fib_id, errno, pal_strerror (errno));

        continue;
      }

    /* set socket as ipv6 only */
    if (ainfo->ai_family == AF_INET6)
      {
        ret = setsockopt(bgp_sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &flags, sizeof(flags));
        if (ret < 0)
          {
            zlog_err (&BLG, "[NETWORK] Server Sock: socket() failed to"
                      "set option for AF=%d, Err:%d-%s", ainfo->ai_family,
                      errno, pal_strerror (errno));
          }
      }

    ret = pal_sock_set_reuseaddr (bgp_sock, PAL_TRUE);
    pal_sock_set_reuseport (bgp_sock, PAL_TRUE);

    /* Bind socket to FIB. */
    ret = pal_sock_set_bindtofib (bgp_sock, fib_id);
    if (ret < 0)
      {
        zlog_err (&BLG, "[NETWORK] Server Sock: bindtofib() Failed for"
                  " AF=%d, Sock %d, FIB-ID %d, Err:%d-%s",
                  ainfo->ai_family, bgp_sock, fib_id, errno,
                  pal_strerror (errno));

        SSOCK_FD_CLOSE (&BLG, bgp_sock);

        ret = 0;

        continue;
      }

    /* If the ai_addr is NULL, bind it to the port. */
    if (ainfo->ai_addr == NULL)
      {
        if (ainfo->ai_family == AF_INET)
          {
            pal_mem_set (&ain4, 0, sizeof (ain4)); 

            ain4.sin_family = AF_INET;
            ain4.sin_port   = pal_hton16 (port);

            ainfo->ai_addr    = (struct pal_sockaddr *) &ain4;
            ainfo->ai_addrlen = sizeof (struct pal_sockaddr_in4);
            addr_set = 1;
          }
        else if (ainfo->ai_family == AF_INET6)
          {
            pal_mem_set (&ain6, 0, sizeof (ain6));

            ain6.sin6_family = AF_INET6;
            ain6.sin6_port   = pal_hton16 (port);

            ainfo->ai_addr    = (struct pal_sockaddr *) &ain6;
            ainfo->ai_addrlen = sizeof (struct pal_sockaddr_in6);
            addr_set = 1;
          }
        else
          {
            zlog_err (&BLG, "[NETWORK] Server Sock: getaddrinfo() returned"
                      "invalid address"
                      " AF=%d, Sock %d",
                      ainfo->ai_family, bgp_sock);
              
            SSOCK_FD_CLOSE (&BLG, bgp_sock);
              
            ret = 0;
              
            continue;
          }
      }

    ret = pal_sock_bind (bgp_sock, ainfo->ai_addr, ainfo->ai_addrlen);

    if (addr_set)
      ainfo->ai_addr = NULL;

    if (ret < 0)
      {
        zlog_err (&BLG, "[NETWORK] Server Sock: bind() Failed for AF="
                  "%d, Err: %d-%s, port[%d]", ainfo->ai_family, errno,
                  pal_strerror (errno),  port);

        SSOCK_FD_CLOSE (&BLG, bgp_sock);

        ret = 0;

        continue;
      }

#ifdef HAVE_TCP_MD5SIG
    bgp_md5_set_server (bgp, bgp_sock);
#endif /* TCP_MD5SIG */

    ret = pal_sock_listen (bgp_sock, BGP_SOCK_LISTEN_BACKLOG);
    if (ret < 0)
      {
        zlog_err (&BLG, "[NETWORK] Server Sock: listen() Failed for "
                  "AF=%d, Sock %d, FIB-ID %d, Err:%d-%s",
                  ainfo->ai_family, bgp_sock, fib_id, errno,
                  pal_strerror (errno));

        SSOCK_FD_CLOSE (&BLG, bgp_sock);

        ret = 0;

        continue;
      }

    /* Start a fresh Accept Thread */
    t_accept = NULL;
    BGP_READ_ON (&BLG, t_accept, bgp, bpn_sock_accept, bgp_sock);

    /* Add thread to Listen Thread List */
    tmp_lnode = XCALLOC (MTYPE_TMP,
                         sizeof (struct bgp_listen_sock_lnode));
    if (! tmp_lnode)
      {
        zlog_err (&BLG, "[NETWORK] Server Sock:"
                  " Cannot allocate memory (%d) @ %s:%d",
                  sizeof (struct bgp_peer_inconn_req), __FILE__, __LINE__);

        SSOCK_FD_CLOSE (&BLG, bgp_sock);
        BGP_READ_OFF (&BLG, t_accept);

        continue;
      }

    tmp_lnode->listen_sock = bgp_sock;
    tmp_lnode->t_accept = t_accept;
    if (bgp->listen_sock_lnode)
      tmp_lnode->next = bgp->listen_sock_lnode;
    bgp->listen_sock_lnode = tmp_lnode;

  } 

  pal_sock_freeaddrinfo (ainfo_head);

  return ret;
}
Esempio n. 4
0
/* May be called multiple times for the same peer */
int
bgp_stop (struct peer *peer)
{
  afi_t afi;
  safi_t safi;
  char orf_name[BUFSIZ];

  /* Can't do this in Clearing; events are used for state transitions */
  if (peer->status != Clearing)
    {
      /* Delete all existing events of the peer */
      BGP_EVENT_FLUSH (peer);
    }

  /* Increment Dropped count. */
  if (peer->status == Established)
    {
      peer->dropped++;

      /* bgp log-neighbor-changes of neighbor Down */
      if (bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
	zlog_info ("%%ADJCHANGE: neighbor %s Down %s", peer->host,
                   peer_down_str [(int) peer->last_reset]);

      /* graceful restart */
      if (peer->t_gr_stale)
	{
	  BGP_TIMER_OFF (peer->t_gr_stale);
	  if (BGP_DEBUG (events, EVENTS))
	    zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
	}
      if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
	{
	  if (BGP_DEBUG (events, EVENTS))
	    {
	      zlog_debug ("%s graceful restart timer started for %d sec",
			  peer->host, peer->v_gr_restart);
	      zlog_debug ("%s graceful restart stalepath timer started for %d sec",
			  peer->host, peer->bgp->stalepath_time);
	    }
	  BGP_TIMER_ON (peer->t_gr_restart, bgp_graceful_restart_timer_expire,
			peer->v_gr_restart);
	  BGP_TIMER_ON (peer->t_gr_stale, bgp_graceful_stale_timer_expire,
			peer->bgp->stalepath_time);
	}
      else
	{
	  UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);

	  for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
	    for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
	      peer->nsf[afi][safi] = 0;
	}

      /* set last reset time */
      peer->resettime = peer->uptime = bgp_clock ();

#ifdef HAVE_SNMP
      bgpTrapBackwardTransition (peer);
#endif /* HAVE_SNMP */

      /* Reset peer synctime */
      peer->synctime = 0;
    }

  /* Stop read and write threads when exists. */
  BGP_READ_OFF (peer->t_read);
  BGP_WRITE_OFF (peer->t_write);

  /* Stop all timers. */
  BGP_TIMER_OFF (peer->t_start);
  BGP_TIMER_OFF (peer->t_connect);
  BGP_TIMER_OFF (peer->t_holdtime);
  BGP_TIMER_OFF (peer->t_keepalive);
  BGP_TIMER_OFF (peer->t_asorig);
  BGP_TIMER_OFF (peer->t_routeadv);

  /* Stream reset. */
  peer->packet_size = 0;

  /* Clear input and output buffer.  */
  if (peer->ibuf)
    stream_reset (peer->ibuf);
  if (peer->work)
    stream_reset (peer->work);
  if (peer->obuf)
    stream_fifo_clean (peer->obuf);

  /* Close of file descriptor. */
  if (peer->fd >= 0)
    {
      close (peer->fd);
      peer->fd = -1;
    }

  for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
    for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
      {
        /* Reset all negotiated variables */
        peer->afc_nego[afi][safi] = 0;
        peer->afc_adv[afi][safi] = 0;
        peer->afc_recv[afi][safi] = 0;

	/* peer address family capability flags*/
	peer->af_cap[afi][safi] = 0;

	/* peer address family status flags*/
	peer->af_sflags[afi][safi] = 0;

	/* Received ORF prefix-filter */
	peer->orf_plist[afi][safi] = NULL;

        /* ORF received prefix-filter pnt */
        sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
        prefix_bgp_orf_remove_all (orf_name);
      }

  /* Reset keepalive and holdtime */
  if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
    {
      peer->v_keepalive = peer->keepalive;
      peer->v_holdtime = peer->holdtime;
    }
  else
    {
      peer->v_keepalive = peer->bgp->default_keepalive;
      peer->v_holdtime = peer->bgp->default_holdtime;
    }

  peer->update_time = 0;

  /* Until we are sure that there is no problem about prefix count
     this should be commented out.*/
#if 0
  /* Reset prefix count */
  peer->pcount[AFI_IP][SAFI_UNICAST] = 0;
  peer->pcount[AFI_IP][SAFI_MULTICAST] = 0;
  peer->pcount[AFI_IP][SAFI_MPLS_VPN] = 0;
  peer->pcount[AFI_IP6][SAFI_UNICAST] = 0;
  peer->pcount[AFI_IP6][SAFI_MULTICAST] = 0;
#endif /* 0 */

  return 0;
}
Esempio n. 5
0
/* Administrative BGP peer stop event. */
int
bgp_stop (struct peer *peer)
{
  int established = 0;
  afi_t afi;
  safi_t safi;
  char orf_name[BUFSIZ];

  /* Increment Dropped count. */
  if (peer->status == Established)
    {
      established = 1;
      peer->dropped++;
      bgp_fsm_change_status (peer, Idle);
#ifdef HAVE_SNMP
      bgpTrapBackwardTransition (peer);
#endif /* HAVE_SNMP */
    }

  /* Reset uptime. */
  bgp_uptime_reset (peer);

  /* Need of clear of peer. */
  if (established)
    bgp_clear_route_all (peer);

  /* Stop read and write threads when exists. */
  BGP_READ_OFF (peer->t_read);
  BGP_WRITE_OFF (peer->t_write);

  /* Stop all timers. */
  BGP_TIMER_OFF (peer->t_start);
  BGP_TIMER_OFF (peer->t_connect);
  BGP_TIMER_OFF (peer->t_holdtime);
  BGP_TIMER_OFF (peer->t_keepalive);
  BGP_TIMER_OFF (peer->t_asorig);
  BGP_TIMER_OFF (peer->t_routeadv);

  /* Delete all existing events of the peer. */
  BGP_EVENT_DELETE (peer);

  /* Stream reset. */
  peer->packet_size = 0;

  /* Clear input and output buffer.  */
  if (peer->ibuf)
    stream_reset (peer->ibuf);
  if (peer->work)
    stream_reset (peer->work);
  stream_fifo_clean (peer->obuf);

  /* Close of file descriptor. */
  if (peer->fd >= 0)
    {
      close (peer->fd);
      peer->fd = -1;
    }

  /* Connection information. */
  if (peer->su_local)
    {
      XFREE (MTYPE_SOCKUNION, peer->su_local);
      peer->su_local = NULL;
    }

  if (peer->su_remote)
    {
      XFREE (MTYPE_SOCKUNION, peer->su_remote);
      peer->su_remote = NULL;
    }

  /* Clear remote router-id. */
  peer->remote_id.s_addr = 0;

  /* Reset all negotiated variables */
  peer->afc_nego[AFI_IP][SAFI_UNICAST] = 0;
  peer->afc_nego[AFI_IP][SAFI_MULTICAST] = 0;
  peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] = 0;
  peer->afc_nego[AFI_IP6][SAFI_UNICAST] = 0;
  peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = 0;
  peer->afc_adv[AFI_IP][SAFI_UNICAST] = 0;
  peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 0;
  peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 0;
  peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 0;
  peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 0;
  peer->afc_recv[AFI_IP][SAFI_UNICAST] = 0;
  peer->afc_recv[AFI_IP][SAFI_MULTICAST] = 0;
  peer->afc_recv[AFI_IP][SAFI_MPLS_VPN] = 0;
  peer->afc_recv[AFI_IP6][SAFI_UNICAST] = 0;
  peer->afc_recv[AFI_IP6][SAFI_MULTICAST] = 0;

  /* Reset route refresh flag. */
  UNSET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
  UNSET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
  UNSET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
  UNSET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
  UNSET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);

  for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
    for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
      {
	/* peer address family capability flags*/
	peer->af_cap[afi][safi] = 0;
	/* peer address family status flags*/
	peer->af_sflags[afi][safi] = 0;
	/* Received ORF prefix-filter */
	peer->orf_plist[afi][safi] = NULL;
        /* ORF received prefix-filter pnt */
        sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
        prefix_bgp_orf_remove_all (orf_name);
      }

  UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
	      PEER_FLAG_DEFAULT_ORIGINATE_CHECK);
  UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
	      PEER_FLAG_DEFAULT_ORIGINATE_CHECK);
  UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
	      PEER_FLAG_DEFAULT_ORIGINATE_CHECK);
  UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
	      PEER_FLAG_DEFAULT_ORIGINATE_CHECK);

  /* Reset keepalive and holdtime */
  if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
    {
      peer->v_keepalive = peer->keepalive;
      peer->v_holdtime = peer->holdtime;
    }
  else
    {
      peer->v_keepalive = peer->bgp->default_keepalive;
      peer->v_holdtime = peer->bgp->default_holdtime;
    }

  peer->update_time = 0;

  /* Until we are sure that there is no problem about prefix count
     this should be commented out.*/
#if 0
  /* Reset prefix count */
  peer->pcount[AFI_IP][SAFI_UNICAST] = 0;
  peer->pcount[AFI_IP][SAFI_MULTICAST] = 0;
  peer->pcount[AFI_IP][SAFI_MPLS_VPN] = 0;
  peer->pcount[AFI_IP6][SAFI_UNICAST] = 0;
  peer->pcount[AFI_IP6][SAFI_MULTICAST] = 0;
#endif /* 0 */

  return 0;
}