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

version 1.1.1.3, 2013/07/21 23:54:37 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 (peer1->sort == 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))
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 241  static int Line 308  static int
 bgp_update_address (struct interface *ifp, const union sockunion *dst,  bgp_update_address (struct interface *ifp, const union sockunion *dst,
                     union sockunion *addr)                      union sockunion *addr)
 {  {
  struct prefix *p, *sel, *d;  struct prefix *p, *sel, d;
   struct connected *connected;    struct connected *connected;
   struct listnode *node;    struct listnode *node;
   int common;    int common;
   
  d = sockunion2hostprefix (dst);  sockunion2hostprefix (dst, &d);
   sel = NULL;    sel = NULL;
   common = -1;    common = -1;
   
   for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))    for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
     {      {
       p = connected->address;        p = connected->address;
      if (p->family != d->family)      if (p->family != d.family)
         continue;          continue;
      if (prefix_common_bits (p, d) > common)      if (prefix_common_bits (p, &d) > common)
         {          {
           sel = p;            sel = p;
          common = prefix_common_bits (sel, d);          common = prefix_common_bits (sel, &d);
         }          }
     }      }
   
   prefix_free (d);  
   if (!sel)    if (!sel)
     return 1;      return 1;
   
Line 299  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 == 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);
       
Line 321  bgp_connect (struct peer *peer) Line 387  bgp_connect (struct peer *peer)
     zlog_err ("%s: could not raise privs", __func__);      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);
 # ifdef HAVE_IPV6  
   else if (sockunion_family (&peer->su) == AF_INET6)    else if (sockunion_family (&peer->su) == AF_INET6)
     setsockopt_ipv6_tclass (peer->fd, IPTOS_PREC_INTERNETCONTROL);      setsockopt_ipv6_tclass (peer->fd, IPTOS_PREC_INTERNETCONTROL);
 # endif  
   if (bgpd_privs.change (ZPRIVS_LOWER))    if (bgpd_privs.change (ZPRIVS_LOWER))
     zlog_err ("%s: could not lower privs", __func__);      zlog_err ("%s: could not lower privs", __func__);
 #endif  #endif
Line 338  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 389  bgp_listener (int sock, struct sockaddr *sa, socklen_t Line 451  bgp_listener (int sock, struct sockaddr *sa, socklen_t
 #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);
 #  ifdef HAVE_IPV6  
   else if (sa->sa_family == AF_INET6)    else if (sa->sa_family == AF_INET6)
     setsockopt_ipv6_tclass (sock, IPTOS_PREC_INTERNETCONTROL);      setsockopt_ipv6_tclass (sock, IPTOS_PREC_INTERNETCONTROL);
 #  endif  
 #endif  #endif
   
   sockopt_v6only (sa->sa_family, sock);    sockopt_v6only (sa->sa_family, sock);
Line 418  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 482  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.3  
changed lines
  Added in v.1.1.1.4


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