Diff for /embedaddon/quagga/bgpd/bgp_network.c between versions 1.1.1.1 and 1.1.1.4

version 1.1.1.1, 2012/02/21 17:26:12 version 1.1.1.4, 2016/11/02 10:09:10
Line 31  Software Foundation, Inc., 59 Temple Place - Suite 330 Line 31  Software Foundation, Inc., 59 Temple Place - Suite 330
 #include "privs.h"  #include "privs.h"
 #include "linklist.h"  #include "linklist.h"
 #include "network.h"  #include "network.h"
   #include "filter.h"
   
 #include "bgpd/bgpd.h"  #include "bgpd/bgpd.h"
 #include "bgpd/bgp_fsm.h"  #include "bgpd/bgp_fsm.h"
Line 47  struct bgp_listener Line 48  struct bgp_listener
   union sockunion su;    union sockunion su;
   struct thread *thread;    struct thread *thread;
 };  };
 /*  /*
  * Set MD5 key for the socket, for the given IPv4 peer address.   * Set MD5 key for the socket, for the given IPv4 peer address.
  * If the password is NULL or zero-length, the option will be disabled.   * If the password is NULL or zero-length, the option will be disabled.
Line 122  bgp_md5_set (struct peer *peer) Line 123  bgp_md5_set (struct peer *peer)
       
   return ret;    return ret;
 }  }
 /* Update BGP socket send buffer size */
 static void
 bgp_update_sock_send_buffer_size (int fd)
 {
   int size = BGP_SOCKET_SNDBUF_SIZE;
   int optval;
   socklen_t optlen = sizeof(optval);
 
   if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &optval, &optlen) < 0)
     {
       zlog_err("getsockopt of SO_SNDBUF failed %s\n", safe_strerror(errno));
       return;
     }
   if (optval < size)
     {
       if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) < 0)
         {
           zlog_err("Couldn't increase send buffer: %s\n", safe_strerror(errno));
         }
     }
 }
 
 static void
 bgp_set_socket_ttl (struct peer *peer, int bgp_sock)
 {
   char buf[INET_ADDRSTRLEN];
   int ret;
 
   /* In case of peer is EBGP, we should set TTL for this connection.  */
   if (!peer->gtsm_hops && (peer_sort (peer) == BGP_PEER_EBGP))
     {
       ret = sockopt_ttl (peer->su.sa.sa_family, bgp_sock, peer->ttl);
       if (ret)
         {
           zlog_err ("%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d",
                     __func__,
                     inet_ntop (AF_INET, &peer->remote_id, buf, sizeof(buf)),
                     errno);
         }
     }
   else if (peer->gtsm_hops)
     {
       /* On Linux, setting minttl without setting ttl seems to mess with the
          outgoing ttl. Therefore setting both.
       */
       ret = sockopt_ttl (peer->su.sa.sa_family, bgp_sock, MAXTTL);
       if (ret)
         {
           zlog_err ("%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d",
                     __func__,
                     inet_ntop (AF_INET, &peer->remote_id, buf, sizeof(buf)),
                     errno);
         }
       ret = sockopt_minttl (peer->su.sa.sa_family, bgp_sock,
                             MAXTTL + 1 - peer->gtsm_hops);
       if (ret)
         {
           zlog_err ("%s: Can't set MinTTL on peer (rtrid %s) socket, err = %d",
                     __func__,
                     inet_ntop (AF_INET, &peer->remote_id, buf, sizeof(buf)),
                     errno);
         }
     }
 }
 
 /* Accept bgp connection. */  /* Accept bgp connection. */
 static int  static int
 bgp_accept (struct thread *thread)  bgp_accept (struct thread *thread)
Line 142  bgp_accept (struct thread *thread) Line 208  bgp_accept (struct thread *thread)
       zlog_err ("accept_sock is nevative value %d", accept_sock);        zlog_err ("accept_sock is nevative value %d", accept_sock);
       return -1;        return -1;
     }      }
  listener->thread = thread_add_read (master, bgp_accept, listener, accept_sock);  listener->thread = thread_add_read (bm->master, bgp_accept, listener, accept_sock);
   
   /* Accept client connection. */    /* Accept client connection. */
   bgp_sock = sockunion_accept (accept_sock, &su);    bgp_sock = sockunion_accept (accept_sock, &su);
Line 153  bgp_accept (struct thread *thread) Line 219  bgp_accept (struct thread *thread)
     }      }
   set_nonblocking (bgp_sock);    set_nonblocking (bgp_sock);
   
     /* Set socket send buffer size */
     bgp_update_sock_send_buffer_size(bgp_sock);
   
   if (BGP_DEBUG (events, EVENTS))    if (BGP_DEBUG (events, EVENTS))
     zlog_debug ("[Event] BGP connection from host %s", inet_sutop (&su, buf));      zlog_debug ("[Event] BGP connection from host %s", inet_sutop (&su, buf));
       
Line 173  bgp_accept (struct thread *thread) Line 242  bgp_accept (struct thread *thread)
       return -1;        return -1;
     }      }
   
  /* In case of peer is EBGP, we should set TTL for this connection.  */  bgp_set_socket_ttl (peer1, bgp_sock);
  if (peer_sort (peer1) == BGP_PEER_EBGP) { 
    sockopt_ttl (peer1->su.sa.sa_family, bgp_sock, peer1->ttl); 
    if (peer1->gtsm_hops) 
      sockopt_minttl (peer1->su.sa.sa_family, bgp_sock, MAXTTL + 1 - peer1->gtsm_hops); 
  } 
   
   /* Make dummy peer until read Open packet. */    /* Make dummy peer until read Open packet. */
   if (BGP_DEBUG (events, EVENTS))    if (BGP_DEBUG (events, EVENTS))
     zlog_debug ("[Event] Make dummy peer structure until read Open packet");      zlog_debug ("[Event] Make dummy peer structure until read Open packet");
   
   {    {
    char buf[SU_ADDRSTRLEN + 1];    char buf[SU_ADDRSTRLEN];
   
     peer = peer_create_accept (peer1->bgp);      peer = peer_create_accept (peer1->bgp);
     SET_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER);      SET_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER);
Line 213  bgp_bind (struct peer *peer) Line 277  bgp_bind (struct peer *peer)
 #ifdef SO_BINDTODEVICE  #ifdef SO_BINDTODEVICE
   int ret;    int ret;
   struct ifreq ifreq;    struct ifreq ifreq;
     int myerrno;
   
   if (! peer->ifname)    if (! peer->ifname)
     return 0;      return 0;
Line 224  bgp_bind (struct peer *peer) Line 289  bgp_bind (struct peer *peer)
       
   ret = setsockopt (peer->fd, SOL_SOCKET, SO_BINDTODEVICE,     ret = setsockopt (peer->fd, SOL_SOCKET, SO_BINDTODEVICE, 
                     &ifreq, sizeof (ifreq));                      &ifreq, sizeof (ifreq));
  myerrno = errno;
   
   if (bgpd_privs.change (ZPRIVS_LOWER) )    if (bgpd_privs.change (ZPRIVS_LOWER) )
     zlog_err ("bgp_bind: could not lower privs");      zlog_err ("bgp_bind: could not lower privs");
   
   if (ret < 0)    if (ret < 0)
     {      {
      zlog (peer->log, LOG_INFO, "bind to interface %s failed", peer->ifname);      zlog (peer->log, LOG_INFO, "bind to interface %s failed, errno=%d",
             peer->ifname, myerrno);
       return ret;        return ret;
     }      }
 #endif /* SO_BINDTODEVICE */  #endif /* SO_BINDTODEVICE */
Line 238  bgp_bind (struct peer *peer) Line 305  bgp_bind (struct peer *peer)
 }  }
   
 static int  static int
bgp_bind_address (int sock, struct in_addr *addr)bgp_update_address (struct interface *ifp, const union sockunion *dst,
                     union sockunion *addr)
 {  {
  int ret;  struct prefix *p, *sel, d;
  struct sockaddr_in local; 
 
  memset (&local, 0, sizeof (struct sockaddr_in)); 
  local.sin_family = AF_INET; 
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN 
  local.sin_len = sizeof(struct sockaddr_in); 
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ 
  memcpy (&local.sin_addr, addr, sizeof (struct in_addr)); 
 
  if ( bgpd_privs.change (ZPRIVS_RAISE) ) 
    zlog_err ("bgp_bind_address: could not raise privs"); 
     
  ret = bind (sock, (struct sockaddr *)&local, sizeof (struct sockaddr_in)); 
  if (ret < 0) 
    ; 
     
  if (bgpd_privs.change (ZPRIVS_LOWER) ) 
    zlog_err ("bgp_bind_address: could not lower privs"); 
     
  return 0; 
} 
 
static struct in_addr * 
bgp_update_address (struct interface *ifp) 
{ 
  struct prefix_ipv4 *p; 
   struct connected *connected;    struct connected *connected;
   struct listnode *node;    struct listnode *node;
     int common;
   
     sockunion2hostprefix (dst, &d);
     sel = NULL;
     common = -1;
   
   for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))    for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
     {      {
      p = (struct prefix_ipv4 *) connected->address;      p = connected->address;
      if (p->family != d.family)
      if (p->family == AF_INET)        continue;
        return &p->prefix;      if (prefix_common_bits (p, &d) > common)
         {
           sel = p;
           common = prefix_common_bits (sel, &d);
         }
     }      }
  return NULL;
   if (!sel)
     return 1;
 
   prefix2sockunion (sel, addr);
   return 0;
 }  }
   
 /* Update source selection.  */  /* Update source selection.  */
Line 285  static void Line 341  static void
 bgp_update_source (struct peer *peer)  bgp_update_source (struct peer *peer)
 {  {
   struct interface *ifp;    struct interface *ifp;
  struct in_addr *addr;  union sockunion addr;
   
   /* Source is specified with interface name.  */    /* Source is specified with interface name.  */
   if (peer->update_if)    if (peer->update_if)
Line 294  bgp_update_source (struct peer *peer) Line 350  bgp_update_source (struct peer *peer)
       if (! ifp)        if (! ifp)
         return;          return;
   
      addr = bgp_update_address (ifp);      if (bgp_update_address (ifp, &peer->su, &addr))
      if (! addr) 
         return;          return;
   
      bgp_bind_address (peer->fd, addr);      sockunion_bind (peer->fd, &addr, 0, &addr);
     }      }
   
   /* Source is specified with IP address.  */    /* Source is specified with IP address.  */
Line 310  bgp_update_source (struct peer *peer) Line 365  bgp_update_source (struct peer *peer)
 int  int
 bgp_connect (struct peer *peer)  bgp_connect (struct peer *peer)
 {  {
  unsigned int ifindex = 0;  ifindex_t ifindex = 0;
   
   /* Make socket for the peer. */    /* Make socket for the peer. */
   peer->fd = sockunion_socket (&peer->su);    peer->fd = sockunion_socket (&peer->su);
   if (peer->fd < 0)    if (peer->fd < 0)
     return -1;      return -1;
   
  /* If we can get socket for the peer, adjest TTL and make connection. */  set_nonblocking (peer->fd);
  if (peer_sort (peer) == BGP_PEER_EBGP) { 
    sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl); 
    if (peer->gtsm_hops) 
      sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - peer->gtsm_hops); 
  } 
   
     /* Set socket send buffer size */
     bgp_update_sock_send_buffer_size(peer->fd);
   
     bgp_set_socket_ttl (peer, peer->fd);
   
   sockopt_reuseaddr (peer->fd);    sockopt_reuseaddr (peer->fd);
   sockopt_reuseport (peer->fd);    sockopt_reuseport (peer->fd);
       
 #ifdef IPTOS_PREC_INTERNETCONTROL  #ifdef IPTOS_PREC_INTERNETCONTROL
     if (bgpd_privs.change (ZPRIVS_RAISE))
       zlog_err ("%s: could not raise privs", __func__);
   if (sockunion_family (&peer->su) == AF_INET)    if (sockunion_family (&peer->su) == AF_INET)
     setsockopt_ipv4_tos (peer->fd, IPTOS_PREC_INTERNETCONTROL);      setsockopt_ipv4_tos (peer->fd, IPTOS_PREC_INTERNETCONTROL);
     else if (sockunion_family (&peer->su) == AF_INET6)
       setsockopt_ipv6_tclass (peer->fd, IPTOS_PREC_INTERNETCONTROL);
     if (bgpd_privs.change (ZPRIVS_LOWER))
       zlog_err ("%s: could not lower privs", __func__);
 #endif  #endif
   
   if (peer->password)    if (peer->password)
Line 341  bgp_connect (struct peer *peer) Line 402  bgp_connect (struct peer *peer)
   /* Update source bind. */    /* Update source bind. */
   bgp_update_source (peer);    bgp_update_source (peer);
   
 #ifdef HAVE_IPV6  
   if (peer->ifname)    if (peer->ifname)
    ifindex = if_nametoindex (peer->ifname);    ifindex = ifname2ifindex (peer->ifname);
#endif /* HAVE_IPV6 */ 
   
   if (BGP_DEBUG (events, EVENTS))    if (BGP_DEBUG (events, EVENTS))
     plog_debug (peer->log, "%s [Event] Connect start to %s fd %d",      plog_debug (peer->log, "%s [Event] Connect start to %s fd %d",
Line 386  bgp_listener (int sock, struct sockaddr *sa, socklen_t Line 445  bgp_listener (int sock, struct sockaddr *sa, socklen_t
   sockopt_reuseaddr (sock);    sockopt_reuseaddr (sock);
   sockopt_reuseport (sock);    sockopt_reuseport (sock);
   
     if (bgpd_privs.change (ZPRIVS_RAISE))
       zlog_err ("%s: could not raise privs", __func__);
   
 #ifdef IPTOS_PREC_INTERNETCONTROL  #ifdef IPTOS_PREC_INTERNETCONTROL
   if (sa->sa_family == AF_INET)    if (sa->sa_family == AF_INET)
     setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL);      setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL);
     else if (sa->sa_family == AF_INET6)
       setsockopt_ipv6_tclass (sock, IPTOS_PREC_INTERNETCONTROL);
 #endif  #endif
   
#ifdef IPV6_V6ONLY  sockopt_v6only (sa->sa_family, sock);
  /* Want only IPV6 on ipv6 socket (not mapped addresses) */ 
  if (sa->sa_family == AF_INET6) { 
    int on = 1; 
    setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, 
                (void *) &on, sizeof (on)); 
  } 
#endif 
   
   if (bgpd_privs.change (ZPRIVS_RAISE) )  
     zlog_err ("bgp_socket: could not raise privs");  
   
   ret = bind (sock, sa, salen);    ret = bind (sock, sa, salen);
   en = errno;    en = errno;
  if (bgpd_privs.change (ZPRIVS_LOWER) )  if (bgpd_privs.change (ZPRIVS_LOWER))
    zlog_err ("bgp_bind_address: could not lower privs");    zlog_err ("%s: could not lower privs", __func__);
   
   if (ret < 0)    if (ret < 0)
     {      {
Line 424  bgp_listener (int sock, struct sockaddr *sa, socklen_t Line 478  bgp_listener (int sock, struct sockaddr *sa, socklen_t
   listener = XMALLOC (MTYPE_BGP_LISTENER, sizeof(*listener));    listener = XMALLOC (MTYPE_BGP_LISTENER, sizeof(*listener));
   listener->fd = sock;    listener->fd = sock;
   memcpy(&listener->su, sa, salen);    memcpy(&listener->su, sa, salen);
  listener->thread = thread_add_read (master, bgp_accept, listener, sock);  listener->thread = thread_add_read (bm->master, bgp_accept, listener, sock);
   listnode_add (bm->listen_sockets, listener);    listnode_add (bm->listen_sockets, listener);
   
   return 0;    return 0;
 }  }
   
 /* IPv6 supported version of BGP server socket setup.  */  /* IPv6 supported version of BGP server socket setup.  */
 #if defined (HAVE_IPV6) && ! defined (NRL)  
 int  int
 bgp_socket (unsigned short port, const char *address)  bgp_socket (unsigned short port, const char *address)
 {  {
Line 488  bgp_socket (unsigned short port, const char *address) Line 541  bgp_socket (unsigned short port, const char *address)
   
   return 0;    return 0;
 }  }
 #else  
 /* Traditional IPv4 only version.  */  
 int  
 bgp_socket (unsigned short port, const char *address)  
 {  
   int sock;  
   int socklen;  
   struct sockaddr_in sin;  
   int ret, en;  
   
   sock = socket (AF_INET, SOCK_STREAM, 0);  
   if (sock < 0)  
     {  
       zlog_err ("socket: %s", safe_strerror (errno));  
       return sock;  
     }  
   
   /* if we intend to implement ttl-security, this socket needs ttl=255 */  
   sockopt_ttl (AF_INET, sock, MAXTTL);  
   
   memset (&sin, 0, sizeof (struct sockaddr_in));  
   sin.sin_family = AF_INET;  
   sin.sin_port = htons (port);  
   socklen = sizeof (struct sockaddr_in);  
   
   if (address && ((ret = inet_aton(address, &sin.sin_addr)) < 1))  
     {  
       zlog_err("bgp_socket: could not parse ip address %s: %s",  
                 address, safe_strerror (errno));  
       return ret;  
     }  
 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN  
   sin.sin_len = socklen;  
 #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */  
   
   ret = bgp_listener (sock, (struct sockaddr *) &sin, socklen);  
   if (ret < 0)   
     {  
       close (sock);  
       return ret;  
     }  
   return sock;  
 }  
 #endif /* HAVE_IPV6 && !NRL */  
   
 void  void
 bgp_close (void)  bgp_close (void)

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.4


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>