File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / bgpd / bgp_network.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jul 21 23:54:37 2013 UTC (10 years, 11 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, HEAD
0.99.22

    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: bgp_md5_set_socket (int socket, union sockunion *su, const char *password)
   57: {
   58:   int ret = -1;
   59:   int en = ENOSYS;
   60:   
   61:   assert (socket >= 0);
   62:   
   63: #if HAVE_DECL_TCP_MD5SIG  
   64:   ret = sockopt_tcp_signature (socket, su, password);
   65:   en  = errno;
   66: #endif /* HAVE_TCP_MD5SIG */
   67:   
   68:   if (ret < 0)
   69:     zlog (NULL, LOG_WARNING, "can't set TCP_MD5SIG option on socket %d: %s",
   70:           socket, safe_strerror (en));
   71: 
   72:   return ret;
   73: }
   74: 
   75: /* Helper for bgp_connect */
   76: static int
   77: bgp_md5_set_connect (int socket, union sockunion *su, const char *password)
   78: {
   79:   int ret = -1;
   80: 
   81: #if HAVE_DECL_TCP_MD5SIG  
   82:   if ( bgpd_privs.change (ZPRIVS_RAISE) )
   83:     {
   84:       zlog_err ("%s: could not raise privs", __func__);
   85:       return ret;
   86:     }
   87:   
   88:   ret = bgp_md5_set_socket (socket, su, password);
   89: 
   90:   if (bgpd_privs.change (ZPRIVS_LOWER) )
   91:     zlog_err ("%s: could not lower privs", __func__);
   92: #endif /* HAVE_TCP_MD5SIG */
   93:   
   94:   return ret;
   95: }
   96: 
   97: int
   98: bgp_md5_set (struct peer *peer)
   99: {
  100:   struct listnode *node;
  101:   int ret = 0;
  102:   struct bgp_listener *listener;
  103: 
  104:   if ( bgpd_privs.change (ZPRIVS_RAISE) )
  105:     {
  106:       zlog_err ("%s: could not raise privs", __func__);
  107:       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:   for (ALL_LIST_ELEMENTS_RO(bm->listen_sockets, node, listener))
  114:     if (listener->su.sa.sa_family == peer->su.sa.sa_family)
  115:       {
  116: 	ret = bgp_md5_set_socket (listener->fd, &peer->su, peer->password);
  117: 	break;
  118:       }
  119: 
  120:   if (bgpd_privs.change (ZPRIVS_LOWER) )
  121:     zlog_err ("%s: could not lower privs", __func__);
  122:   
  123:   return ret;
  124: }
  125: 
  126: /* Accept bgp connection. */
  127: static int
  128: bgp_accept (struct thread *thread)
  129: {
  130:   int bgp_sock;
  131:   int accept_sock;
  132:   union sockunion su;
  133:   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:   accept_sock = THREAD_FD (thread);
  140:   if (accept_sock < 0)
  141:     {
  142:       zlog_err ("accept_sock is nevative value %d", accept_sock);
  143:       return -1;
  144:     }
  145:   listener->thread = thread_add_read (master, bgp_accept, listener, accept_sock);
  146: 
  147:   /* Accept client connection. */
  148:   bgp_sock = sockunion_accept (accept_sock, &su);
  149:   if (bgp_sock < 0)
  150:     {
  151:       zlog_err ("[Error] BGP socket accept failed (%s)", safe_strerror (errno));
  152:       return -1;
  153:     }
  154:   set_nonblocking (bgp_sock);
  155: 
  156:   if (BGP_DEBUG (events, EVENTS))
  157:     zlog_debug ("[Event] BGP connection from host %s", inet_sutop (&su, buf));
  158:   
  159:   /* Check remote IP address */
  160:   peer1 = peer_lookup (NULL, &su);
  161:   if (! peer1 || peer1->status == Idle)
  162:     {
  163:       if (BGP_DEBUG (events, EVENTS))
  164: 	{
  165: 	  if (! peer1)
  166: 	    zlog_debug ("[Event] BGP connection IP address %s is not configured",
  167: 		       inet_sutop (&su, buf));
  168: 	  else
  169: 	    zlog_debug ("[Event] BGP connection IP address %s is Idle state",
  170: 		       inet_sutop (&su, buf));
  171: 	}
  172:       close (bgp_sock);
  173:       return -1;
  174:     }
  175: 
  176:   /* In case of peer is EBGP, we should set TTL for this connection.  */
  177:   if (peer1->sort == BGP_PEER_EBGP) {
  178:     sockopt_ttl (peer1->su.sa.sa_family, bgp_sock, peer1->ttl);
  179:     if (peer1->gtsm_hops)
  180:       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:   if (BGP_DEBUG (events, EVENTS))
  185:     zlog_debug ("[Event] Make dummy peer structure until read Open packet");
  186: 
  187:   {
  188:     char buf[SU_ADDRSTRLEN];
  189: 
  190:     peer = peer_create_accept (peer1->bgp);
  191:     SET_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER);
  192:     peer->su = su;
  193:     peer->fd = bgp_sock;
  194:     peer->status = Active;
  195:     peer->local_id = peer1->local_id;
  196:     peer->v_holdtime = peer1->v_holdtime;
  197:     peer->v_keepalive = peer1->v_keepalive;
  198: 
  199:     /* Make peer's address string. */
  200:     sockunion2str (&su, buf, SU_ADDRSTRLEN);
  201:     peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
  202:   }
  203: 
  204:   BGP_EVENT_ADD (peer, TCP_connection_open);
  205: 
  206:   return 0;
  207: }
  208: 
  209: /* BGP socket bind. */
  210: static int
  211: bgp_bind (struct peer *peer)
  212: {
  213: #ifdef SO_BINDTODEVICE
  214:   int ret;
  215:   struct ifreq ifreq;
  216: 
  217:   if (! peer->ifname)
  218:     return 0;
  219: 
  220:   strncpy ((char *)&ifreq.ifr_name, peer->ifname, sizeof (ifreq.ifr_name));
  221: 
  222:   if ( bgpd_privs.change (ZPRIVS_RAISE) )
  223:   	zlog_err ("bgp_bind: could not raise privs");
  224:   
  225:   ret = setsockopt (peer->fd, SOL_SOCKET, SO_BINDTODEVICE, 
  226: 		    &ifreq, sizeof (ifreq));
  227: 
  228:   if (bgpd_privs.change (ZPRIVS_LOWER) )
  229:     zlog_err ("bgp_bind: could not lower privs");
  230: 
  231:   if (ret < 0)
  232:     {
  233:       zlog (peer->log, LOG_INFO, "bind to interface %s failed", peer->ifname);
  234:       return ret;
  235:     }
  236: #endif /* SO_BINDTODEVICE */
  237:   return 0;
  238: }
  239: 
  240: static int
  241: 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:   d = sockunion2hostprefix (dst);
  250:   sel = NULL;
  251:   common = -1;
  252: 
  253:   for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
  254:     {
  255:       p = connected->address;
  256:       if (p->family != d->family)
  257: 	continue;
  258:       if (prefix_common_bits (p, d) > common)
  259: 	{
  260: 	  sel = p;
  261: 	  common = prefix_common_bits (sel, d);
  262: 	}
  263:     }
  264: 
  265:   prefix_free (d);
  266:   if (!sel)
  267:     return 1;
  268: 
  269:   prefix2sockunion (sel, addr);
  270:   return 0;
  271: }
  272: 
  273: /* Update source selection.  */
  274: static void
  275: bgp_update_source (struct peer *peer)
  276: {
  277:   struct interface *ifp;
  278:   union sockunion addr;
  279: 
  280:   /* Source is specified with interface name.  */
  281:   if (peer->update_if)
  282:     {
  283:       ifp = if_lookup_by_name (peer->update_if);
  284:       if (! ifp)
  285: 	return;
  286: 
  287:       if (bgp_update_address (ifp, &peer->su, &addr))
  288: 	return;
  289: 
  290:       sockunion_bind (peer->fd, &addr, 0, &addr);
  291:     }
  292: 
  293:   /* Source is specified with IP address.  */
  294:   if (peer->update_source)
  295:     sockunion_bind (peer->fd, peer->update_source, 0, peer->update_source);
  296: }
  297: 
  298: /* BGP try to connect to the peer.  */
  299: int
  300: bgp_connect (struct peer *peer)
  301: {
  302:   unsigned int ifindex = 0;
  303: 
  304:   /* Make socket for the peer. */
  305:   peer->fd = sockunion_socket (&peer->su);
  306:   if (peer->fd < 0)
  307:     return -1;
  308: 
  309:   /* If we can get socket for the peer, adjest TTL and make connection. */
  310:   if (peer->sort == BGP_PEER_EBGP) {
  311:     sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
  312:     if (peer->gtsm_hops)
  313:       sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - peer->gtsm_hops);
  314:   }
  315: 
  316:   sockopt_reuseaddr (peer->fd);
  317:   sockopt_reuseport (peer->fd);
  318:   
  319: #ifdef IPTOS_PREC_INTERNETCONTROL
  320:   if (bgpd_privs.change (ZPRIVS_RAISE))
  321:     zlog_err ("%s: could not raise privs", __func__);
  322:   if (sockunion_family (&peer->su) == AF_INET)
  323:     setsockopt_ipv4_tos (peer->fd, IPTOS_PREC_INTERNETCONTROL);
  324: # ifdef HAVE_IPV6
  325:   else if (sockunion_family (&peer->su) == AF_INET6)
  326:     setsockopt_ipv6_tclass (peer->fd, IPTOS_PREC_INTERNETCONTROL);
  327: # endif
  328:   if (bgpd_privs.change (ZPRIVS_LOWER))
  329:     zlog_err ("%s: could not lower privs", __func__);
  330: #endif
  331: 
  332:   if (peer->password)
  333:     bgp_md5_set_connect (peer->fd, &peer->su, peer->password);
  334: 
  335:   /* Bind socket. */
  336:   bgp_bind (peer);
  337: 
  338:   /* Update source bind. */
  339:   bgp_update_source (peer);
  340: 
  341: #ifdef HAVE_IPV6
  342:   if (peer->ifname)
  343:     ifindex = if_nametoindex (peer->ifname);
  344: #endif /* HAVE_IPV6 */
  345: 
  346:   if (BGP_DEBUG (events, EVENTS))
  347:     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:   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: bgp_getsockname (struct peer *peer)
  357: {
  358:   if (peer->su_local)
  359:     {
  360:       sockunion_free (peer->su_local);
  361:       peer->su_local = NULL;
  362:     }
  363: 
  364:   if (peer->su_remote)
  365:     {
  366:       sockunion_free (peer->su_remote);
  367:       peer->su_remote = NULL;
  368:     }
  369: 
  370:   peer->su_local = sockunion_getsockname (peer->fd);
  371:   peer->su_remote = sockunion_getpeername (peer->fd);
  372: 
  373:   bgp_nexthop_set (peer->su_local, peer->su_remote, &peer->nexthop, peer);
  374: }
  375: 
  376: 
  377: static int
  378: bgp_listener (int sock, struct sockaddr *sa, socklen_t salen)
  379: {
  380:   struct bgp_listener *listener;
  381:   int ret, en;
  382: 
  383:   sockopt_reuseaddr (sock);
  384:   sockopt_reuseport (sock);
  385: 
  386:   if (bgpd_privs.change (ZPRIVS_RAISE))
  387:     zlog_err ("%s: could not raise privs", __func__);
  388: 
  389: #ifdef IPTOS_PREC_INTERNETCONTROL
  390:   if (sa->sa_family == AF_INET)
  391:     setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL);
  392: #  ifdef HAVE_IPV6
  393:   else if (sa->sa_family == AF_INET6)
  394:     setsockopt_ipv6_tclass (sock, IPTOS_PREC_INTERNETCONTROL);
  395: #  endif
  396: #endif
  397: 
  398:   sockopt_v6only (sa->sa_family, sock);
  399: 
  400:   ret = bind (sock, sa, salen);
  401:   en = errno;
  402:   if (bgpd_privs.change (ZPRIVS_LOWER))
  403:     zlog_err ("%s: could not lower privs", __func__);
  404: 
  405:   if (ret < 0)
  406:     {
  407:       zlog_err ("bind: %s", safe_strerror (en));
  408:       return ret;
  409:     }
  410: 
  411:   ret = listen (sock, 3);
  412:   if (ret < 0)
  413:     {
  414:       zlog_err ("listen: %s", safe_strerror (errno));
  415:       return ret;
  416:     }
  417: 
  418:   listener = XMALLOC (MTYPE_BGP_LISTENER, sizeof(*listener));
  419:   listener->fd = sock;
  420:   memcpy(&listener->su, sa, salen);
  421:   listener->thread = thread_add_read (master, bgp_accept, listener, sock);
  422:   listnode_add (bm->listen_sockets, listener);
  423: 
  424:   return 0;
  425: }
  426: 
  427: /* IPv6 supported version of BGP server socket setup.  */
  428: #if defined (HAVE_IPV6) && ! defined (NRL)
  429: int
  430: 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:   snprintf (port_str, sizeof(port_str), "%d", port);
  443:   port_str[sizeof (port_str) - 1] = '\0';
  444: 
  445:   ret = getaddrinfo (address, port_str, &req, &ainfo_save);
  446:   if (ret != 0)
  447:     {
  448:       zlog_err ("getaddrinfo: %s", gai_strerror (ret));
  449:       return -1;
  450:     }
  451: 
  452:   count = 0;
  453:   for (ainfo = ainfo_save; ainfo; ainfo = ainfo->ai_next)
  454:     {
  455:       int sock;
  456: 
  457:       if (ainfo->ai_family != AF_INET && ainfo->ai_family != AF_INET6)
  458: 	continue;
  459:      
  460:       sock = socket (ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol);
  461:       if (sock < 0)
  462: 	{
  463: 	  zlog_err ("socket: %s", safe_strerror (errno));
  464: 	  continue;
  465: 	}
  466: 	
  467:       /* if we intend to implement ttl-security, this socket needs ttl=255 */
  468:       sockopt_ttl (ainfo->ai_family, sock, MAXTTL);
  469:       
  470:       ret = bgp_listener (sock, ainfo->ai_addr, ainfo->ai_addrlen);
  471:       if (ret == 0)
  472: 	++count;
  473:       else
  474: 	close(sock);
  475:     }
  476:   freeaddrinfo (ainfo_save);
  477:   if (count == 0)
  478:     {
  479:       zlog_err ("%s: no usable addresses", __func__);
  480:       return -1;
  481:     }
  482: 
  483:   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: bgp_close (void)
  532: {
  533:   struct listnode *node, *next;
  534:   struct bgp_listener *listener;
  535: 
  536:   for (ALL_LIST_ELEMENTS (bm->listen_sockets, node, next, listener))
  537:     {
  538:       thread_cancel (listener->thread);
  539:       close (listener->fd);
  540:       listnode_delete (bm->listen_sockets, listener);
  541:       XFREE (MTYPE_BGP_LISTENER, listener);
  542:     }
  543: }

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