bgp_network.c
上传用户:xiaozhuqw
上传日期:2009-11-15
资源大小:1338k
文件大小:9k
源码类别:

网络

开发平台:

Unix_Linux

  1. /* BGP network related fucntions
  2.    Copyright (C) 1999 Kunihiro Ishiguro
  3. This file is part of GNU Zebra.
  4. GNU Zebra is free software; you can redistribute it and/or modify it
  5. under the terms of the GNU General Public License as published by the
  6. Free Software Foundation; either version 2, or (at your option) any
  7. later version.
  8. GNU Zebra is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNU Zebra; see the file COPYING.  If not, write to the Free
  14. Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  15. 02111-1307, USA.  */
  16. #include <zebra.h>
  17. #include "thread.h"
  18. #include "sockunion.h"
  19. #include "memory.h"
  20. #include "log.h"
  21. #include "if.h"
  22. #include "prefix.h"
  23. #include "command.h"
  24. #include "bgpd/bgpd.h"
  25. #include "bgpd/bgp_fsm.h"
  26. #include "bgpd/bgp_attr.h"
  27. #include "bgpd/bgp_debug.h"
  28. #include "bgpd/bgp_network.h"
  29. #ifdef HAVE_TCP_SIGNATURE
  30. #include "bgpd/bgp_tcpsig.h"
  31. #endif /* HAVE_TCP_SIGNATURE */
  32. /* Accept bgp connection. */
  33. static int
  34. bgp_accept (struct thread *thread)
  35. {
  36.   int bgp_sock;
  37.   int accept_sock;
  38.   union sockunion su;
  39.   struct peer *peer;
  40.   struct peer *peer1;
  41.   struct bgp *bgp;
  42.   char buf[SU_ADDRSTRLEN];
  43.   /* Regiser accept thread. */
  44.   accept_sock = THREAD_FD (thread);
  45.   bgp = THREAD_ARG (thread);
  46.   if (accept_sock < 0)
  47.     {
  48.       zlog_err ("accept_sock is nevative value %d", accept_sock);
  49.       return -1;
  50.     }
  51.   thread_add_read (master, bgp_accept, bgp, accept_sock);
  52.   /* Accept client connection. */
  53.   bgp_sock = sockunion_accept (accept_sock, &su);
  54.   if (bgp_sock < 0)
  55.     {
  56.       zlog_err ("[Error] BGP socket accept failed (%s)", strerror (errno));
  57.       return -1;
  58.     }
  59.   if (BGP_DEBUG (events, EVENTS))
  60.     zlog_info ("[Event] BGP connection from host %s", inet_sutop (&su, buf));
  61.   
  62.   /* Check remote IP address */
  63.   peer1 = peer_lookup (bgp, &su);
  64.   if (! peer1 || peer1->status == Idle)
  65.     {
  66.       if (BGP_DEBUG (events, EVENTS))
  67. {
  68.   if (! peer1)
  69.     zlog_info ("[Event] BGP connection IP address %s is not configured",
  70.        inet_sutop (&su, buf));
  71.   else
  72.     zlog_info ("[Event] BGP connection IP address %s is Idle state",
  73.        inet_sutop (&su, buf));
  74. }
  75.       close (bgp_sock);
  76.       return -1;
  77.     }
  78.   /* In case of peer is EBGP, we should set TTL for this connection.  */
  79.   if (peer_sort (peer1) == BGP_PEER_EBGP)
  80.     sockopt_ttl (peer1->su.sa.sa_family, bgp_sock, peer1->ttl);
  81.   if (! bgp)
  82.     bgp = peer1->bgp;
  83.   /* Make dummy peer until read Open packet. */
  84.   if (BGP_DEBUG (events, EVENTS))
  85.     zlog_info ("[Event] Make dummy peer structure until read Open packet");
  86.   {
  87.     char buf[SU_ADDRSTRLEN + 1];
  88.     peer = peer_create_accept (bgp);
  89.     SET_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER);
  90.     peer->su = su;
  91.     peer->fd = bgp_sock;
  92.     peer->status = Active;
  93.     peer->local_id = peer1->local_id;
  94.     /* Make peer's address string. */
  95.     sockunion2str (&su, buf, SU_ADDRSTRLEN);
  96.     peer->host = strdup (buf);
  97.   }
  98.   BGP_EVENT_ADD (peer, TCP_connection_open);
  99.   return 0;
  100. }
  101. /* BGP socket bind. */
  102. int
  103. bgp_bind (struct peer *peer)
  104. {
  105. #ifdef SO_BINDTODEVICE
  106.   int ret;
  107.   struct ifreq ifreq;
  108.   if (! peer->ifname)
  109.     return 0;
  110.   strncpy ((char *)&ifreq.ifr_name, peer->ifname, sizeof (ifreq.ifr_name));
  111.   ret = setsockopt (peer->fd, SOL_SOCKET, SO_BINDTODEVICE, 
  112.     &ifreq, sizeof (ifreq));
  113.   if (ret < 0)
  114.     {
  115.       zlog (peer->log, LOG_INFO, "bind to interface %s failed", peer->ifname);
  116.       return ret;
  117.     }
  118. #endif /* SO_BINDTODEVICE */
  119.   return 0;
  120. }
  121. int
  122. bgp_bind_address (int sock, struct in_addr *addr)
  123. {
  124.   int ret;
  125.   struct sockaddr_in local;
  126.   memset (&local, 0, sizeof (struct sockaddr_in));
  127.   local.sin_family = AF_INET;
  128. #ifdef HAVE_SIN_LEN
  129.   local.sin_len = sizeof(struct sockaddr_in);
  130. #endif /* HAVE_SIN_LEN */
  131.   memcpy (&local.sin_addr, addr, sizeof (struct in_addr));
  132.   ret = bind (sock, (struct sockaddr *)&local, sizeof (struct sockaddr_in));
  133.   if (ret < 0)
  134.     ;
  135.   return 0;
  136. }
  137. struct in_addr *
  138. bgp_update_address (struct interface *ifp)
  139. {
  140.   struct prefix_ipv4 *p;
  141.   struct connected *connected;
  142.   listnode node;
  143.   for (node = listhead (ifp->connected); node; nextnode (node))
  144.     {
  145.       connected = getdata (node);
  146.       p = (struct prefix_ipv4 *) connected->address;
  147.       if (p->family == AF_INET)
  148. return &p->prefix;
  149.     }
  150.   return NULL;
  151. }
  152. /* Update source selection.  */
  153. void
  154. bgp_update_source (struct peer *peer)
  155. {
  156.   struct interface *ifp;
  157.   struct in_addr *addr;
  158.   /* Source is specified with interface name.  */
  159.   if (peer->update_if)
  160.     {
  161.       ifp = if_lookup_by_name (peer->update_if);
  162.       if (! ifp)
  163. return;
  164.       addr = bgp_update_address (ifp);
  165.       if (! addr)
  166. return;
  167.       bgp_bind_address (peer->fd, addr);
  168.     }
  169.   /* Source is specified with IP address.  */
  170.   if (peer->update_source)
  171.     sockunion_bind (peer->fd, peer->update_source, 0, peer->update_source);
  172. }
  173. /* BGP try to connect to the peer.  */
  174. int
  175. bgp_connect (struct peer *peer)
  176. {
  177.   unsigned int ifindex = 0;
  178.   /* Make socket for the peer. */
  179.   peer->fd = sockunion_socket (&peer->su);
  180.   if (peer->fd < 0)
  181.     return -1;
  182.   /* If we can get socket for the peer, adjest TTL and make connection. */
  183.   if (peer_sort (peer) == BGP_PEER_EBGP)
  184.     sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
  185.   sockopt_reuseaddr (peer->fd);
  186.   sockopt_reuseport (peer->fd);
  187.   /* Bind socket. */
  188.   bgp_bind (peer);
  189.   /* Update source bind. */
  190.   bgp_update_source (peer);
  191. #ifdef HAVE_IPV6
  192.   if (peer->ifname)
  193.     ifindex = if_nametoindex (peer->ifname);
  194. #endif /* HAVE_IPV6 */
  195.   if (BGP_DEBUG (events, EVENTS))
  196.     plog_info (peer->log, "%s [Event] Connect start to %s fd %d",
  197.        peer->host, peer->host, peer->fd);
  198. #ifdef HAVE_TCP_SIGNATURE
  199.   if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSWORD))
  200.     bgp_tcpsig_set (peer->fd, peer);
  201. #endif /* HAVE_TCP_SIGNATURE */
  202.   /* Connect to the remote peer. */
  203.   return sockunion_connect (peer->fd, &peer->su, htons (peer->port), ifindex);
  204. }
  205. /* After TCP connection is established.  Get local address and port. */
  206. void
  207. bgp_getsockname (struct peer *peer)
  208. {
  209.   if (peer->su_local)
  210.     {
  211.       XFREE (MTYPE_TMP, peer->su_local);
  212.       peer->su_local = NULL;
  213.     }
  214.   if (peer->su_remote)
  215.     {
  216.       XFREE (MTYPE_TMP, peer->su_remote);
  217.       peer->su_remote = NULL;
  218.     }
  219.   peer->su_local = sockunion_getsockname (peer->fd);
  220.   peer->su_remote = sockunion_getpeername (peer->fd);
  221.   bgp_nexthop_set (peer->su_local, peer->su_remote, &peer->nexthop, peer);
  222. }
  223. /* IPv6 supported version of BGP server socket setup.  */
  224. #if defined (HAVE_IPV6) && ! defined (NRL)
  225. int
  226. bgp_socket (struct bgp *bgp, unsigned short port)
  227. {
  228.   int ret;
  229.   struct addrinfo req;
  230.   struct addrinfo *ainfo;
  231.   struct addrinfo *ainfo_save;
  232.   int sock = 0;
  233.   char port_str[BUFSIZ];
  234.   memset (&req, 0, sizeof (struct addrinfo));
  235.   req.ai_flags = AI_PASSIVE;
  236.   req.ai_family = AF_UNSPEC;
  237.   req.ai_socktype = SOCK_STREAM;
  238.   sprintf (port_str, "%d", port);
  239.   port_str[sizeof (port_str) - 1] = '';
  240.   ret = getaddrinfo (NULL, port_str, &req, &ainfo);
  241.   if (ret != 0)
  242.     {
  243.       zlog_err ("getaddrinfo: %s", gai_strerror (ret));
  244.       return -1;
  245.     }
  246.   ainfo_save = ainfo;
  247.   do
  248.     {
  249.       if (ainfo->ai_family != AF_INET && ainfo->ai_family != AF_INET6)
  250. continue;
  251.      
  252.       sock = socket (ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol);
  253.       if (sock < 0)
  254. {
  255.   zlog_err ("socket: %s", strerror (errno));
  256.   continue;
  257. }
  258.       sockopt_reuseaddr (sock);
  259.       sockopt_reuseport (sock);
  260.       ret = bind (sock, ainfo->ai_addr, ainfo->ai_addrlen);
  261.       if (ret < 0)
  262. {
  263.   zlog_err ("bind: %s", strerror (errno));
  264.   close (sock);
  265.   continue;
  266. }
  267.       ret = listen (sock, 3);
  268.       if (ret < 0) 
  269. {
  270.   zlog_err ("listen: %s", strerror (errno));
  271.   close (sock);
  272.   continue;
  273. }
  274. #ifdef HAVE_TCP_SIGNATURE
  275. #ifdef HAVE_LINUX_TCP_SIGNATURE
  276.       bm->sock = sock;
  277. #endif /* HAVE_LINUX_TCP_SIGNATURE */
  278. #ifdef HAVE_OPENBSD_TCP_SIGNATURE
  279.       bgp_tcpsig_set (sock, 0);
  280.       bm->sock = -1;
  281. #endif /* HAVE_OPENBSD_TCP_SIGNATURE */
  282. #endif /* HAVE_TCP_SIGNATURE */
  283.       thread_add_read (master, bgp_accept, bgp, sock);
  284.     }
  285.   while ((ainfo = ainfo->ai_next) != NULL);
  286.   freeaddrinfo (ainfo_save);
  287.   return sock;
  288. }
  289. #else
  290. /* Traditional IPv4 only version.  */
  291. int
  292. bgp_socket (struct bgp *bgp, unsigned short port)
  293. {
  294.   int sock;
  295.   int socklen;
  296.   struct sockaddr_in sin;
  297.   int ret;
  298.   sock = socket (AF_INET, SOCK_STREAM, 0);
  299.   if (sock < 0)
  300.     {
  301.       zlog_err ("socket: %s", strerror (errno));
  302.       return sock;
  303.     }
  304.   sockopt_reuseaddr (sock);
  305.   sockopt_reuseport (sock);
  306.   memset (&sin, 0, sizeof (struct sockaddr_in));
  307.   sin.sin_family = AF_INET;
  308.   sin.sin_port = htons (port);
  309.   socklen = sizeof (struct sockaddr_in);
  310. #ifdef HAVE_SIN_LEN
  311.   sin.sin_len = socklen;
  312. #endif /* HAVE_SIN_LEN */
  313.   ret = bind (sock, (struct sockaddr *) &sin, socklen);
  314.   if (ret < 0)
  315.     {
  316.       zlog_err ("bind: %s", strerror (errno));
  317.       close (sock);
  318.       return ret;
  319.     }
  320.   ret = listen (sock, 3);
  321.   if (ret < 0) 
  322.     {
  323.       zlog_err ("listen: %s", strerror (errno));
  324.       close (sock);
  325.       return ret;
  326.     }
  327. #ifdef HAVE_TCP_SIGNATURE
  328. #ifdef HAVE_LINUX_TCP_SIGNATURE
  329.   bm->sock = sock;
  330. #endif /* HAVE_LINUX_TCP_SIGNATURE */
  331. #ifdef HAVE_OPENBSD_TCP_SIGNATURE
  332.   bgp_tcpsig_set (sock, 0);
  333.   bm->sock = -1;
  334. #endif /* HAVE_OPENBSD_TCP_SIGNATURE */
  335. #endif /* HAVE_TCP_SIGNATURE */
  336.   thread_add_read (bm->master, bgp_accept, bgp, sock);
  337.   return sock;
  338. }
  339. #endif /* HAVE_IPV6 && !NRL */