LCOV - code coverage report
Current view: top level - bgpd - bgp_network.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 3 207 1.4 %
Date: 2015-11-19 Functions: 1 12 8.3 %

          Line data    Source code
       1             : /* BGP network related fucntions
       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 "sockunion.h"
      25             : #include "sockopt.h"
      26             : #include "memory.h"
      27             : #include "log.h"
      28             : #include "if.h"
      29             : #include "prefix.h"
      30             : #include "command.h"
      31             : #include "privs.h"
      32             : #include "linklist.h"
      33             : #include "network.h"
      34             : 
      35             : #include "bgpd/bgpd.h"
      36             : #include "bgpd/bgp_fsm.h"
      37             : #include "bgpd/bgp_attr.h"
      38             : #include "bgpd/bgp_debug.h"
      39             : #include "bgpd/bgp_network.h"
      40             : 
      41             : extern struct zebra_privs_t bgpd_privs;
      42             : 
      43             : /* BGP listening socket. */
      44             : struct bgp_listener
      45             : {
      46             :   int fd;
      47             :   union sockunion su;
      48             :   struct thread *thread;
      49             : };
      50             : 
      51             : /*
      52             :  * Set MD5 key for the socket, for the given IPv4 peer address.
      53             :  * If the password is NULL or zero-length, the option will be disabled.
      54             :  */
      55             : static int
      56           0 : bgp_md5_set_socket (int socket, union sockunion *su, const char *password)
      57             : {
      58           0 :   int ret = -1;
      59           0 :   int en = ENOSYS;
      60             :   
      61           0 :   assert (socket >= 0);
      62             :   
      63             : #if HAVE_DECL_TCP_MD5SIG  
      64           0 :   ret = sockopt_tcp_signature (socket, su, password);
      65           0 :   en  = errno;
      66             : #endif /* HAVE_TCP_MD5SIG */
      67             :   
      68           0 :   if (ret < 0)
      69           0 :     zlog (NULL, LOG_WARNING, "can't set TCP_MD5SIG option on socket %d: %s",
      70             :           socket, safe_strerror (en));
      71             : 
      72           0 :   return ret;
      73             : }
      74             : 
      75             : /* Helper for bgp_connect */
      76             : static int
      77           0 : bgp_md5_set_connect (int socket, union sockunion *su, const char *password)
      78             : {
      79           0 :   int ret = -1;
      80             : 
      81             : #if HAVE_DECL_TCP_MD5SIG  
      82           0 :   if ( bgpd_privs.change (ZPRIVS_RAISE) )
      83             :     {
      84           0 :       zlog_err ("%s: could not raise privs", __func__);
      85           0 :       return ret;
      86             :     }
      87             :   
      88           0 :   ret = bgp_md5_set_socket (socket, su, password);
      89             : 
      90           0 :   if (bgpd_privs.change (ZPRIVS_LOWER) )
      91           0 :     zlog_err ("%s: could not lower privs", __func__);
      92             : #endif /* HAVE_TCP_MD5SIG */
      93             :   
      94           0 :   return ret;
      95             : }
      96             : 
      97             : int
      98           0 : bgp_md5_set (struct peer *peer)
      99             : {
     100             :   struct listnode *node;
     101           0 :   int ret = 0;
     102             :   struct bgp_listener *listener;
     103             : 
     104           0 :   if ( bgpd_privs.change (ZPRIVS_RAISE) )
     105             :     {
     106           0 :       zlog_err ("%s: could not raise privs", __func__);
     107           0 :       return -1;
     108             :     }
     109             :   
     110             :   /* Just set the password on the listen socket(s). Outbound connections
     111             :    * are taken care of in bgp_connect() below.
     112             :    */
     113           0 :   for (ALL_LIST_ELEMENTS_RO(bm->listen_sockets, node, listener))
     114           0 :     if (listener->su.sa.sa_family == peer->su.sa.sa_family)
     115             :       {
     116           0 :         ret = bgp_md5_set_socket (listener->fd, &peer->su, peer->password);
     117           0 :         break;
     118             :       }
     119             : 
     120           0 :   if (bgpd_privs.change (ZPRIVS_LOWER) )
     121           0 :     zlog_err ("%s: could not lower privs", __func__);
     122             :   
     123           0 :   return ret;
     124             : }
     125             : 
     126             : /* Accept bgp connection. */
     127             : static int
     128           0 : bgp_accept (struct thread *thread)
     129             : {
     130             :   int bgp_sock;
     131             :   int accept_sock;
     132             :   union sockunion su;
     133           0 :   struct bgp_listener *listener = THREAD_ARG(thread);
     134             :   struct peer *peer;
     135             :   struct peer *peer1;
     136             :   char buf[SU_ADDRSTRLEN];
     137             : 
     138             :   /* Register accept thread. */
     139           0 :   accept_sock = THREAD_FD (thread);
     140           0 :   if (accept_sock < 0)
     141             :     {
     142           0 :       zlog_err ("accept_sock is nevative value %d", accept_sock);
     143           0 :       return -1;
     144             :     }
     145           0 :   listener->thread = thread_add_read (master, bgp_accept, listener, accept_sock);
     146             : 
     147             :   /* Accept client connection. */
     148           0 :   bgp_sock = sockunion_accept (accept_sock, &su);
     149           0 :   if (bgp_sock < 0)
     150             :     {
     151           0 :       zlog_err ("[Error] BGP socket accept failed (%s)", safe_strerror (errno));
     152           0 :       return -1;
     153             :     }
     154           0 :   set_nonblocking (bgp_sock);
     155             : 
     156           0 :   if (BGP_DEBUG (events, EVENTS))
     157           0 :     zlog_debug ("[Event] BGP connection from host %s", inet_sutop (&su, buf));
     158             :   
     159             :   /* Check remote IP address */
     160           0 :   peer1 = peer_lookup (NULL, &su);
     161           0 :   if (! peer1 || peer1->status == Idle)
     162             :     {
     163           0 :       if (BGP_DEBUG (events, EVENTS))
     164             :         {
     165           0 :           if (! peer1)
     166           0 :             zlog_debug ("[Event] BGP connection IP address %s is not configured",
     167             :                        inet_sutop (&su, buf));
     168             :           else
     169           0 :             zlog_debug ("[Event] BGP connection IP address %s is Idle state",
     170             :                        inet_sutop (&su, buf));
     171             :         }
     172           0 :       close (bgp_sock);
     173           0 :       return -1;
     174             :     }
     175             : 
     176             :   /* In case of peer is EBGP, we should set TTL for this connection.  */
     177           0 :   if (peer1->sort == BGP_PEER_EBGP) {
     178           0 :     sockopt_ttl (peer1->su.sa.sa_family, bgp_sock, peer1->ttl);
     179           0 :     if (peer1->gtsm_hops)
     180           0 :       sockopt_minttl (peer1->su.sa.sa_family, bgp_sock, MAXTTL + 1 - peer1->gtsm_hops);
     181             :   }
     182             : 
     183             :   /* Make dummy peer until read Open packet. */
     184           0 :   if (BGP_DEBUG (events, EVENTS))
     185           0 :     zlog_debug ("[Event] Make dummy peer structure until read Open packet");
     186             : 
     187             :   {
     188             :     char buf[SU_ADDRSTRLEN];
     189             : 
     190           0 :     peer = peer_create_accept (peer1->bgp);
     191           0 :     SET_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER);
     192           0 :     peer->su = su;
     193           0 :     peer->fd = bgp_sock;
     194           0 :     peer->status = Active;
     195           0 :     peer->local_id = peer1->local_id;
     196           0 :     peer->v_holdtime = peer1->v_holdtime;
     197           0 :     peer->v_keepalive = peer1->v_keepalive;
     198             : 
     199             :     /* Make peer's address string. */
     200           0 :     sockunion2str (&su, buf, SU_ADDRSTRLEN);
     201           0 :     peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
     202             :   }
     203             : 
     204           0 :   BGP_EVENT_ADD (peer, TCP_connection_open);
     205             : 
     206           0 :   return 0;
     207             : }
     208             : 
     209             : /* BGP socket bind. */
     210             : static int
     211           0 : bgp_bind (struct peer *peer)
     212             : {
     213             : #ifdef SO_BINDTODEVICE
     214             :   int ret;
     215             :   struct ifreq ifreq;
     216             : 
     217           0 :   if (! peer->ifname)
     218           0 :     return 0;
     219             : 
     220           0 :   strncpy ((char *)&ifreq.ifr_name, peer->ifname, sizeof (ifreq.ifr_name));
     221             : 
     222           0 :   if ( bgpd_privs.change (ZPRIVS_RAISE) )
     223           0 :         zlog_err ("bgp_bind: could not raise privs");
     224             :   
     225           0 :   ret = setsockopt (peer->fd, SOL_SOCKET, SO_BINDTODEVICE, 
     226             :                     &ifreq, sizeof (ifreq));
     227             : 
     228           0 :   if (bgpd_privs.change (ZPRIVS_LOWER) )
     229           0 :     zlog_err ("bgp_bind: could not lower privs");
     230             : 
     231           0 :   if (ret < 0)
     232             :     {
     233           0 :       zlog (peer->log, LOG_INFO, "bind to interface %s failed", peer->ifname);
     234           0 :       return ret;
     235             :     }
     236             : #endif /* SO_BINDTODEVICE */
     237           0 :   return 0;
     238             : }
     239             : 
     240             : static int
     241           0 : bgp_update_address (struct interface *ifp, const union sockunion *dst,
     242             :                     union sockunion *addr)
     243             : {
     244             :   struct prefix *p, *sel, *d;
     245             :   struct connected *connected;
     246             :   struct listnode *node;
     247             :   int common;
     248             : 
     249           0 :   d = sockunion2hostprefix (dst);
     250           0 :   sel = NULL;
     251           0 :   common = -1;
     252             : 
     253           0 :   for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
     254             :     {
     255           0 :       p = connected->address;
     256           0 :       if (p->family != d->family)
     257           0 :         continue;
     258           0 :       if (prefix_common_bits (p, d) > common)
     259             :         {
     260           0 :           sel = p;
     261           0 :           common = prefix_common_bits (sel, d);
     262             :         }
     263             :     }
     264             : 
     265           0 :   prefix_free (d);
     266           0 :   if (!sel)
     267           0 :     return 1;
     268             : 
     269           0 :   prefix2sockunion (sel, addr);
     270           0 :   return 0;
     271             : }
     272             : 
     273             : /* Update source selection.  */
     274             : static void
     275           0 : bgp_update_source (struct peer *peer)
     276             : {
     277             :   struct interface *ifp;
     278             :   union sockunion addr;
     279             : 
     280             :   /* Source is specified with interface name.  */
     281           0 :   if (peer->update_if)
     282             :     {
     283           0 :       ifp = if_lookup_by_name (peer->update_if);
     284           0 :       if (! ifp)
     285           0 :         return;
     286             : 
     287           0 :       if (bgp_update_address (ifp, &peer->su, &addr))
     288           0 :         return;
     289             : 
     290           0 :       sockunion_bind (peer->fd, &addr, 0, &addr);
     291             :     }
     292             : 
     293             :   /* Source is specified with IP address.  */
     294           0 :   if (peer->update_source)
     295           0 :     sockunion_bind (peer->fd, peer->update_source, 0, peer->update_source);
     296             : }
     297             : 
     298             : /* BGP try to connect to the peer.  */
     299             : int
     300           0 : bgp_connect (struct peer *peer)
     301             : {
     302           0 :   unsigned int ifindex = 0;
     303             : 
     304             :   /* Make socket for the peer. */
     305           0 :   peer->fd = sockunion_socket (&peer->su);
     306           0 :   if (peer->fd < 0)
     307           0 :     return -1;
     308             : 
     309             :   /* If we can get socket for the peer, adjest TTL and make connection. */
     310           0 :   if (peer->sort == BGP_PEER_EBGP) {
     311           0 :     sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
     312           0 :     if (peer->gtsm_hops)
     313           0 :       sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - peer->gtsm_hops);
     314             :   }
     315             : 
     316           0 :   sockopt_reuseaddr (peer->fd);
     317           0 :   sockopt_reuseport (peer->fd);
     318             :   
     319             : #ifdef IPTOS_PREC_INTERNETCONTROL
     320           0 :   if (bgpd_privs.change (ZPRIVS_RAISE))
     321           0 :     zlog_err ("%s: could not raise privs", __func__);
     322           0 :   if (sockunion_family (&peer->su) == AF_INET)
     323           0 :     setsockopt_ipv4_tos (peer->fd, IPTOS_PREC_INTERNETCONTROL);
     324             : # ifdef HAVE_IPV6
     325           0 :   else if (sockunion_family (&peer->su) == AF_INET6)
     326           0 :     setsockopt_ipv6_tclass (peer->fd, IPTOS_PREC_INTERNETCONTROL);
     327             : # endif
     328           0 :   if (bgpd_privs.change (ZPRIVS_LOWER))
     329           0 :     zlog_err ("%s: could not lower privs", __func__);
     330             : #endif
     331             : 
     332           0 :   if (peer->password)
     333           0 :     bgp_md5_set_connect (peer->fd, &peer->su, peer->password);
     334             : 
     335             :   /* Bind socket. */
     336           0 :   bgp_bind (peer);
     337             : 
     338             :   /* Update source bind. */
     339           0 :   bgp_update_source (peer);
     340             : 
     341             : #ifdef HAVE_IPV6
     342           0 :   if (peer->ifname)
     343           0 :     ifindex = if_nametoindex (peer->ifname);
     344             : #endif /* HAVE_IPV6 */
     345             : 
     346           0 :   if (BGP_DEBUG (events, EVENTS))
     347           0 :     plog_debug (peer->log, "%s [Event] Connect start to %s fd %d",
     348             :                peer->host, peer->host, peer->fd);
     349             : 
     350             :   /* Connect to the remote peer. */
     351           0 :   return sockunion_connect (peer->fd, &peer->su, htons (peer->port), ifindex);
     352             : }
     353             : 
     354             : /* After TCP connection is established.  Get local address and port. */
     355             : void
     356           0 : bgp_getsockname (struct peer *peer)
     357             : {
     358           0 :   if (peer->su_local)
     359             :     {
     360           0 :       sockunion_free (peer->su_local);
     361           0 :       peer->su_local = NULL;
     362             :     }
     363             : 
     364           0 :   if (peer->su_remote)
     365             :     {
     366           0 :       sockunion_free (peer->su_remote);
     367           0 :       peer->su_remote = NULL;
     368             :     }
     369             : 
     370           0 :   peer->su_local = sockunion_getsockname (peer->fd);
     371           0 :   peer->su_remote = sockunion_getpeername (peer->fd);
     372             : 
     373           0 :   bgp_nexthop_set (peer->su_local, peer->su_remote, &peer->nexthop, peer);
     374           0 : }
     375             : 
     376             : 
     377             : static int
     378           0 : bgp_listener (int sock, struct sockaddr *sa, socklen_t salen)
     379             : {
     380             :   struct bgp_listener *listener;
     381             :   int ret, en;
     382             : 
     383           0 :   sockopt_reuseaddr (sock);
     384           0 :   sockopt_reuseport (sock);
     385             : 
     386           0 :   if (bgpd_privs.change (ZPRIVS_RAISE))
     387           0 :     zlog_err ("%s: could not raise privs", __func__);
     388             : 
     389             : #ifdef IPTOS_PREC_INTERNETCONTROL
     390           0 :   if (sa->sa_family == AF_INET)
     391           0 :     setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL);
     392             : #  ifdef HAVE_IPV6
     393           0 :   else if (sa->sa_family == AF_INET6)
     394           0 :     setsockopt_ipv6_tclass (sock, IPTOS_PREC_INTERNETCONTROL);
     395             : #  endif
     396             : #endif
     397             : 
     398           0 :   sockopt_v6only (sa->sa_family, sock);
     399             : 
     400           0 :   ret = bind (sock, sa, salen);
     401           0 :   en = errno;
     402           0 :   if (bgpd_privs.change (ZPRIVS_LOWER))
     403           0 :     zlog_err ("%s: could not lower privs", __func__);
     404             : 
     405           0 :   if (ret < 0)
     406             :     {
     407           0 :       zlog_err ("bind: %s", safe_strerror (en));
     408           0 :       return ret;
     409             :     }
     410             : 
     411           0 :   ret = listen (sock, 3);
     412           0 :   if (ret < 0)
     413             :     {
     414           0 :       zlog_err ("listen: %s", safe_strerror (errno));
     415           0 :       return ret;
     416             :     }
     417             : 
     418           0 :   listener = XMALLOC (MTYPE_BGP_LISTENER, sizeof(*listener));
     419           0 :   listener->fd = sock;
     420           0 :   memcpy(&listener->su, sa, salen);
     421           0 :   listener->thread = thread_add_read (master, bgp_accept, listener, sock);
     422           0 :   listnode_add (bm->listen_sockets, listener);
     423             : 
     424           0 :   return 0;
     425             : }
     426             : 
     427             : /* IPv6 supported version of BGP server socket setup.  */
     428             : #if defined (HAVE_IPV6) && ! defined (NRL)
     429             : int
     430           0 : bgp_socket (unsigned short port, const char *address)
     431             : {
     432             :   struct addrinfo *ainfo;
     433             :   struct addrinfo *ainfo_save;
     434             :   static const struct addrinfo req = {
     435             :     .ai_family = AF_UNSPEC,
     436             :     .ai_flags = AI_PASSIVE,
     437             :     .ai_socktype = SOCK_STREAM,
     438             :   };
     439             :   int ret, count;
     440             :   char port_str[BUFSIZ];
     441             : 
     442           0 :   snprintf (port_str, sizeof(port_str), "%d", port);
     443           0 :   port_str[sizeof (port_str) - 1] = '\0';
     444             : 
     445           0 :   ret = getaddrinfo (address, port_str, &req, &ainfo_save);
     446           0 :   if (ret != 0)
     447             :     {
     448           0 :       zlog_err ("getaddrinfo: %s", gai_strerror (ret));
     449           0 :       return -1;
     450             :     }
     451             : 
     452           0 :   count = 0;
     453           0 :   for (ainfo = ainfo_save; ainfo; ainfo = ainfo->ai_next)
     454             :     {
     455             :       int sock;
     456             : 
     457           0 :       if (ainfo->ai_family != AF_INET && ainfo->ai_family != AF_INET6)
     458           0 :         continue;
     459             :      
     460           0 :       sock = socket (ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol);
     461           0 :       if (sock < 0)
     462             :         {
     463           0 :           zlog_err ("socket: %s", safe_strerror (errno));
     464           0 :           continue;
     465             :         }
     466             :         
     467             :       /* if we intend to implement ttl-security, this socket needs ttl=255 */
     468           0 :       sockopt_ttl (ainfo->ai_family, sock, MAXTTL);
     469             :       
     470           0 :       ret = bgp_listener (sock, ainfo->ai_addr, ainfo->ai_addrlen);
     471           0 :       if (ret == 0)
     472           0 :         ++count;
     473             :       else
     474           0 :         close(sock);
     475             :     }
     476           0 :   freeaddrinfo (ainfo_save);
     477           0 :   if (count == 0)
     478             :     {
     479           0 :       zlog_err ("%s: no usable addresses", __func__);
     480           0 :       return -1;
     481             :     }
     482             : 
     483           0 :   return 0;
     484             : }
     485             : #else
     486             : /* Traditional IPv4 only version.  */
     487             : int
     488             : bgp_socket (unsigned short port, const char *address)
     489             : {
     490             :   int sock;
     491             :   int socklen;
     492             :   struct sockaddr_in sin;
     493             :   int ret, en;
     494             : 
     495             :   sock = socket (AF_INET, SOCK_STREAM, 0);
     496             :   if (sock < 0)
     497             :     {
     498             :       zlog_err ("socket: %s", safe_strerror (errno));
     499             :       return sock;
     500             :     }
     501             : 
     502             :   /* if we intend to implement ttl-security, this socket needs ttl=255 */
     503             :   sockopt_ttl (AF_INET, sock, MAXTTL);
     504             : 
     505             :   memset (&sin, 0, sizeof (struct sockaddr_in));
     506             :   sin.sin_family = AF_INET;
     507             :   sin.sin_port = htons (port);
     508             :   socklen = sizeof (struct sockaddr_in);
     509             : 
     510             :   if (address && ((ret = inet_aton(address, &sin.sin_addr)) < 1))
     511             :     {
     512             :       zlog_err("bgp_socket: could not parse ip address %s: %s",
     513             :                 address, safe_strerror (errno));
     514             :       return ret;
     515             :     }
     516             : #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
     517             :   sin.sin_len = socklen;
     518             : #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
     519             : 
     520             :   ret = bgp_listener (sock, (struct sockaddr *) &sin, socklen);
     521             :   if (ret < 0) 
     522             :     {
     523             :       close (sock);
     524             :       return ret;
     525             :     }
     526             :   return sock;
     527             : }
     528             : #endif /* HAVE_IPV6 && !NRL */
     529             : 
     530             : void
     531           1 : bgp_close (void)
     532             : {
     533             :   struct listnode *node, *next;
     534             :   struct bgp_listener *listener;
     535             : 
     536           1 :   for (ALL_LIST_ELEMENTS (bm->listen_sockets, node, next, listener))
     537             :     {
     538           0 :       thread_cancel (listener->thread);
     539           0 :       close (listener->fd);
     540           0 :       listnode_delete (bm->listen_sockets, listener);
     541           0 :       XFREE (MTYPE_BGP_LISTENER, listener);
     542             :     }
     543           1 : }

Generated by: LCOV version 1.10