Ejemplo n.º 1
0
/* After TCP connection is established.  Get local address and port. */
int bgp_getsockname(struct peer *peer)
{
	if (peer->su_local) {
		sockunion_free(peer->su_local);
		peer->su_local = NULL;
	}

	if (peer->su_remote) {
		sockunion_free(peer->su_remote);
		peer->su_remote = NULL;
	}

	peer->su_local = sockunion_getsockname(peer->fd);
	if (!peer->su_local)
		return -1;
	peer->su_remote = sockunion_getpeername(peer->fd);
	if (!peer->su_remote)
		return -1;

	if (!bgp_zebra_nexthop_set(peer->su_local, peer->su_remote,
				   &peer->nexthop, peer)) {
		flog_err(EC_BGP_NH_UPD,
			 "%s: nexthop_set failed, resetting connection - intf %p",
			 peer->host, peer->nexthop.ifp);
		return -1;
	}
	return 0;
}
/* After TCP connection is established.  Get local address and port. */
void
bgp_getsockname (struct peer *peer)
{
  if (peer->su_local)
    {
      sockunion_free (peer->su_local);
      peer->su_local = NULL;
    }

  if (peer->su_remote)
    {
      sockunion_free (peer->su_remote);
      peer->su_remote = NULL;
    }

  peer->su_local = sockunion_getsockname (peer->fd);
  peer->su_remote = sockunion_getpeername (peer->fd);

  bgp_nexthop_set (peer->su_local, peer->su_remote, &peer->nexthop, peer);
}
Ejemplo n.º 3
0
/* This function is the first starting point of all BGP connection. It
   try to connect to remote peer with non-blocking IO. */
int
bgp_start (struct peer *peer)
{
  int status;

  if (BGP_PEER_START_SUPPRESSED (peer))
    {
      if (BGP_DEBUG (fsm, FSM))
        plog_err (peer->log, "%s [FSM] Trying to start suppressed peer"
                  " - this is never supposed to happen!", peer->host);
      return -1;
    }

  /* Scrub some information that might be left over from a previous,
   * session
   */
  /* Connection information. */
  if (peer->su_local)
    {
      sockunion_free (peer->su_local);
      peer->su_local = NULL;
    }

  if (peer->su_remote)
    {
      sockunion_free (peer->su_remote);
      peer->su_remote = NULL;
    }

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

  /* Clear peer capability flag. */
  peer->cap = 0;
    
  /* If the peer is passive mode, force to move to Active mode. */
  if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
    {
      BGP_EVENT_ADD (peer, TCP_connection_open_failed);
      return 0;
    }

  status = bgp_connect (peer);

  switch (status)
    {
    case connect_error:
      if (BGP_DEBUG (fsm, FSM))
	plog_debug (peer->log, "%s [FSM] Connect error", peer->host);
      BGP_EVENT_ADD (peer, TCP_connection_open_failed);
      break;
    case connect_success:
      if (BGP_DEBUG (fsm, FSM))
	plog_debug (peer->log, "%s [FSM] Connect immediately success",
		   peer->host);
      BGP_EVENT_ADD (peer, TCP_connection_open);
      break;
    case connect_in_progress:
      /* To check nonblocking connect, we wait until socket is
         readable or writable. */
      if (BGP_DEBUG (fsm, FSM))
	plog_debug (peer->log, "%s [FSM] Non blocking connect waiting result",
		   peer->host);
      if (peer->fd < 0)
	{
	  zlog_err ("bgp_start peer's fd is negative value %d",
		    peer->fd);
	  return -1;
	}
      BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
      BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
      break;
    }
  return 0;
}
Ejemplo n.º 4
0
int
sockopt_tcp_signature (int sock, union sockunion *su, const char *password)
{
#define CONFIG_TCP_MD5SIG 1 
#define TCP_MD5SIG        14
#define GNU_LINUX         1

#if defined(HAVE_TCP_MD5_LINUX24) && defined(GNU_LINUX)

  /* Support for the old Linux 2.4 TCP-MD5 patch, taken from Hasso Tepper's
   * version of the Quagga patch (based on work by Rick Payne, and Bruce
   * Simpson)
   */
#define TCP_MD5_AUTH 13
#define TCP_MD5_AUTH_ADD 1
#define TCP_MD5_AUTH_DEL 2
  struct tcp_rfc2385_cmd {
    u_int8_t     command;    /* Command - Add/Delete */
    u_int32_t    address;    /* IPV4 address associated */
    u_int8_t     keylen;     /* MD5 Key len (do NOT assume 0 terminated ascii) */
    void         *key;       /* MD5 Key */
  } cmd;
  struct in_addr *addr = &su->sin.sin_addr;
  
  cmd.command = (password != NULL ? TCP_MD5_AUTH_ADD : TCP_MD5_AUTH_DEL);
  cmd.address = addr->s_addr;
  cmd.keylen = (password != NULL ? strlen (password) : 0);
  cmd.key = password;
  
  return setsockopt (sock, IPPROTO_TCP, TCP_MD5_AUTH, &cmd, sizeof cmd);
  
#elif CONFIG_TCP_MD5SIG

	
  int ret;
#ifndef GNU_LINUX
  /*
   * XXX Need to do PF_KEY operation here to add/remove an SA entry,
   * and add/remove an SP entry for this peer's packet flows also.
   */
  int md5sig = password && *password ? 1 : 0;
  

#else

  struct  {
	  struct {
		  unsigned short  ss_family; 
		  char __data[128 - sizeof(unsigned short)];
	  } tcpm_addr; /* address associated */
	  __u16   __tcpm_pad1;				  /* zero */
	  __u16   tcpm_keylen;				  /* key length */
	  __u32   __tcpm_pad2;				  /* zero */
	  __u8	  tcpm_key[80];	  /* key (binary) */
  } md5sig;

  //struct tcp_md5sig md5sig;
  int keylen = 0;
  union sockunion *su2, *susock;

  if(NULL != password)
  	keylen = strlen(password) ;
  
  /* Figure out whether the socket and the sockunion are the same family..
   * adding AF_INET to AF_INET6 needs to be v4 mapped, you'd think..
   */
   susock = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
   if(NULL == susock)
   	{
   	    return -1;
   	}
  if (!( sockunion_getsockname (sock, susock)))
    return -1;
  
  if (susock->sa.sa_family == su->sa.sa_family)
    su2 = su;
  else
    {
      /* oops.. */
      su2 = susock;
      
      if (su2->sa.sa_family == AF_INET)
        {
          sockunion_free (susock);
          return 0;
        }
      
#ifdef HAVE_IPV6

      /* If this does not work, then all users of this sockopt will need to
       * differentiate between IPv4 and IPv6, and keep seperate sockets for
       * each. 
       *
       * Sadly, it doesn't seem to work at present. It's unknown whether
       * this is a bug or not.
       */
      if (su2->sa.sa_family == AF_INET6
          && su->sa.sa_family == AF_INET)
        {
           su2->sin6.sin6_family = AF_INET6;
           /* V4Map the address */
           memset (&su2->sin6.sin6_addr, 0, sizeof (struct in6_addr));
           su2->sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
           memcpy (&su2->sin6.sin6_addr.s6_addr32[3], &su->sin.sin_addr, 4);
        }
#endif
    }
  
  memset (&md5sig, 0, sizeof (md5sig));
  memcpy (&md5sig.tcpm_addr, su2, sizeof (*su2));
  md5sig.tcpm_keylen = keylen;
  if (keylen)
    memcpy (md5sig.tcpm_key, password, keylen);
  sockunion_free (susock);
#endif /* GNU_LINUX */

  if ((ret = setsockopt (sock, IPPROTO_TCP, TCP_MD5SIG, &md5sig, sizeof md5sig)) < 0)
    {
      /* ENOENT is harmless.  It is returned when we clear a password for which
	 one was not previously set. */
      if (ENOENT == errno)
	ret = 0;
      else
	zlog_err ("sockopt_tcp_signature: setsockopt(%d): %s",
		  sock, safe_strerror(errno));
    }
  return ret;
#else /* HAVE_TCP_MD5SIG */
  return -2;
#endif /* !HAVE_TCP_MD5SIG */



}
Ejemplo n.º 5
0
int
sockopt_tcp_signature (int sock, union sockunion *su, const char *password)
{
#if HAVE_DECL_TCP_MD5SIG
  int ret;
#ifndef GNU_LINUX
  /*
   * XXX Need to do PF_KEY operation here to add/remove an SA entry,
   * and add/remove an SP entry for this peer's packet flows also.
   */
  int md5sig = password && *password ? 1 : 0;
#else
  int keylen = password ? strlen (password) : 0;
  struct tcp_md5sig md5sig;
  union sockunion *su2, *susock;
  
  /* Figure out whether the socket and the sockunion are the same family..
   * adding AF_INET to AF_INET6 needs to be v4 mapped, you'd think..
   */
  if (!(susock = sockunion_getsockname (sock)))
    return -1;
  
  if (susock->sa.sa_family == su->sa.sa_family)
    su2 = su;
  else
    {
      /* oops.. */
      su2 = susock;
      
      if (su2->sa.sa_family == AF_INET)
        {
          sockunion_free (susock);
          return -1;
        };
      
      /* If this does not work, then all users of this sockopt will need to
       * differentiate between IPv4 and IPv6, and keep seperate sockets for
       * each. 
       *
       * Sadly, it doesn't seem to work at present. It's unknown whether
       * this is a bug or not.
       */
      if (su2->sa.sa_family == AF_INET6
          && su->sa.sa_family == AF_INET)
        {
           su2->sin6.sin6_family = AF_INET6;
           /* V4Map the address */
           memset (&su2->sin6.sin6_addr, 0, sizeof (struct in6_addr));
           su2->sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
           memcpy (&su2->sin6.sin6_addr.s6_addr32[3], &su->sin.sin_addr, 4);
        }
    }
  
  memset (&md5sig, 0, sizeof (md5sig));
  memcpy (&md5sig.tcpm_addr, su2, sizeof (*su2));
  md5sig.tcpm_keylen = keylen;
  if (keylen)
    memcpy (md5sig.tcpm_key, password, keylen);
  sockunion_free (susock);
#endif /* GNU_LINUX */
  ret = setsockopt (sock, IPPROTO_TCP, TCP_MD5SIG, &md5sig, sizeof md5sig);
  return ret;
#else /* HAVE_TCP_MD5SIG */
  return -2;
#endif /* HAVE_TCP_MD5SIG */
}