File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / bgpd / bgp_network.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:10 2016 UTC (7 years, 8 months ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

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

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