⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bgp.c

📁 同时支持IPv4和IPv6的BGP协议实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Copyright (C) 1998 WIDE Project. * All rights reserved. *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. *  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include "include.h"#include "bgp.h"#include "router.h"#include "task.h"#include "rt_table.h"#include "aspath.h"#include "bgp_var.h"#include "in6.h"#include "ripng.h"#include "ripng_var.h"int          bgpsock;              /* socket for BGP tcp communication *//* socket buffer size for outgoing BGP data */int          bgpsbsize = BGP_DEFAULT_SBSIZE;u_int16_t    my_as_number;         /* my AS number                     */u_int32_t    bgpIdentifier;        /* BGP Identifier  (net-order)      */u_int32_t    clusterId;            /* CLUSTER_ID                       */u_int16_t    bgpHoldtime = BGP_HOLDTIME; /* hold timer */byte         IamRR;                /* I am Route Reflector             *//* lists */struct rpcb *bgb;byte         outpkt[BGPMAXPACKETSIZE];static int bgp_selectroute __P((struct rt_entry *, struct rpcb *));/* *  bgp_connect_start() *    DESCRIPTION *       Initiate  connection-trying  to other BGP peer. *        It's first called by main(), after this, called by bgp_cease(). */ voidbgp_connect_start(struct rpcb *bnp){  task        *tsk;  extern task *taskhead;  if (bnp->rp_mode & BGPO_PASSIVE)    fatalx("<bgp_connect_start>: BUG !");  /*  "New" socket()  */   if ((bnp->rp_socket = socket(AF_INET6, SOCK_STREAM, 0)) == -1)    fatal("<bgp_connect_start>: socket");  bnp->rp_adj_ribs_in = NULL;           /*  <--- for safety.          */  bnp->rp_stat.rps_connretry++;  MALLOC(tsk, task);  if (taskhead) {    insque(tsk, taskhead);  /* will be sorted later by connect_try()    */  } else {    tsk->tsk_next = tsk->tsk_prev = tsk;    taskhead      = tsk;  }  tsk->tsk_timename         = BGP_CONNECT_TIMER;  tsk->tsk_bgp              = bnp;#ifdef DEBUG  tsk->tsk_timefull.tv_sec  = BGPCONN_SHORT;#else  /*   * The suggested value for the ConnectRetry timer is 120 seconds.   * RFC 1771 Section 6.4   */  tsk->tsk_timefull.tv_sec  = bnp->rp_stat.rps_connretry * BGPCONN_SHORT;  if (tsk->tsk_timefull.tv_sec > 120)    tsk->tsk_timefull.tv_sec = 120;#endif  tsk->tsk_timefull.tv_usec = 0;  bnp->rp_connect_timer     = tsk;  bnp->rp_state             = BGPSTATE_CONNECT;  if ((logflags & LOG_BGPSTATE) != 0)    syslog(LOG_NOTICE, "<%s>: BGP state shift[%s] peer: %s", __FUNCTION__,	   bgp_statestr[bnp->rp_state], bgp_peerstr(bnp));  if (!(bnp->rp_mode & BGPO_IFSTATIC))  /* <--- need.   */    bnp->rp_ife = NULL;  /*  ConnectRetry timer ON. */  task_timer_update(bnp->rp_connect_timer);}/* *   connect_try() *       Triggerd by SIGALRM (if and only-if). */ voidconnect_try(struct rpcb *bnp){#ifdef ADVANCEDAPI  int                 on;#endif  int                 optval, optlen;  int                 childpid;  extern task   *taskhead;  extern fd_set  fdmask;  if (bnp->rp_mode & BGPO_PASSIVE ||      bnp->rp_socket == -1)    fatalx("<connect_try>: BUG !");  /* CONNECT state - trying to connect */  bnp->rp_state = BGPSTATE_CONNECT;  if ((logflags & LOG_BGPSTATE) != 0)    syslog(LOG_NOTICE, "<%s>: BGP state shift[%s] peer: %s", __FUNCTION__,	   bgp_statestr[bnp->rp_state], bgp_peerstr(bnp));  /* If specfied, set source address */  if (!IN6_IS_ADDR_UNSPECIFIED(&bnp->rp_lcladdr.sin6_addr) &&      bind(bnp->rp_socket, (struct sockaddr *)&bnp->rp_lcladdr,	   sizeof(bnp->rp_lcladdr)) < 0) {	  syslog(LOG_ERR, "<%s>: bind: %s", __FUNCTION__, strerror(errno));	  fatalx("bind failed");  }  optval = 1; optlen = sizeof(optval);  if (setsockopt(bnp->rp_socket, SOL_SOCKET, SO_REUSEADDR,		 (int *)&optval, optlen) < 0) {    fatal("<connect_try>: setsockopt: SO_REUSEADDR");  }#ifdef ADVANCEDAPI  on = 1;#ifdef IPV6_RECVPKTINFO  if (setsockopt(bnp->rp_socket, IPPROTO_IPV6, IPV6_RECVPKTINFO,		 &on, sizeof(on)) < 0)    fatal("<connect_try>: setsockopt: IPV6_RECVPKTINFO");#else  /* old adv API */  if (setsockopt(bnp->rp_socket, IPPROTO_IPV6, IPV6_PKTINFO,		 &on, sizeof(on)) < 0)    fatal("<connect_try>: setsockopt: IPV6_PKTINFO");#endif   if (bnp->rp_mode & BGPO_IFSTATIC) {    static struct in6_pktinfo *pktinfo = NULL;#ifndef USE_RFC2292BIS    static struct cmsghdr     *cmsgp = NULL;#endif#ifdef USE_RFC2292BIS    if (pktinfo == NULL &&	(pktinfo = (struct in6_pktinfo *)malloc(sizeof(*pktinfo))) == NULL)      fatalx("<connect_try>: malloc");    memset(pktinfo, 0, sizeof(struct in6_pktinfo));    pktinfo->ipi6_ifindex = bnp->rp_ife->ifi_ifn->if_index;    if (setsockopt(bnp->rp_socket, IPPROTO_IPV6, IPV6_PKTINFO,		   (void *)pktinfo, sizeof(*pktinfo)) < 0)      fatal("<connect_try>: setsockopt(IPV6_PKTINFO)");#else  /* old advanced API */    if (cmsgp == NULL &&	(cmsgp =	 (struct cmsghdr *)malloc(CMSG_SPACE(sizeof(struct in6_pktinfo))))	== NULL)      fatalx("<connect_try>: malloc");    memset(cmsgp, 0, CMSG_SPACE(sizeof(struct in6_pktinfo)));    cmsgp->cmsg_len   = CMSG_LEN(sizeof(struct in6_pktinfo));    cmsgp->cmsg_level = IPPROTO_IPV6;    cmsgp->cmsg_type  = IPV6_PKTINFO;    pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsgp);    pktinfo->ipi6_ifindex = bnp->rp_ife->ifi_ifn->if_index;    if (setsockopt(bnp->rp_socket, IPPROTO_IPV6, IPV6_PKTOPTIONS,		   (void *)cmsgp,		   CMSG_SPACE(sizeof(struct in6_pktinfo)))	< 0)      fatal("<connect_try>: setsockopt");#endif   }#endif /* ADVANCEDAPI */  childpid = 0;  if (s_pipe(bnp->rp_sfd) < 0)    terminate();  if ((logflags & LOG_BGPCONNECT) != 0)    syslog(LOG_DEBUG, "<connect_try>: <s_pipe>: sfd[0]=%d, sfd[1]=%d ",	   bnp->rp_sfd[0], bnp->rp_sfd[1]);  if ((childpid = fork()) < 0) {    dperror("<connect_try>: fork");    terminate();  }  if (childpid == 0) {    /*****  Child  *****//*    close(bnp->rp_sfd[0]); */    if (connect(bnp->rp_socket, 		(struct sockaddr *)&bnp->rp_addr, /* global or linklocal*/		sizeof(bnp->rp_addr)) == 0)    {      if ((logflags & LOG_BGPCONNECT) != 0) 	syslog(LOG_DEBUG,	       "<%s>: <child>: connection succeed with %s (%s AS %d)",	       __FUNCTION__, ip6str(&bnp->rp_addr.sin6_addr, 0),	       ((bnp->rp_mode & BGPO_IGP) ? "Internal" : "External"),	       bnp->rp_as);    } else {      syslog(LOG_NOTICE,	     "<%s>: <child>: connect failed for %s: %s", __FUNCTION__,	     bgp_peerstr(bnp), strerror(errno));      if ((logflags & LOG_BGPCONNECT) != 0)	syslog(LOG_DEBUG, "\t\t\t by %s %s",	       ip6str(&bnp->rp_addr.sin6_addr, 0),	       (bnp->rp_mode & BGPO_IFSTATIC) ?	       bnp->rp_ife->ifi_ifn->if_name : "");      close(bnp->rp_socket);      bnp->rp_socket = -1;    }    if ((bgpd_sendfile(bnp->rp_sfd[1], bnp->rp_socket)) < 0) {      exit(1);    } else {      exit(0);    }  } /***  End of child  ***/  /******  Parent  ******//*  close(bnp->rp_sfd[1]);*/  FD_SET(bnp->rp_sfd[0] , &fdmask);  /*  Clear ConnectRetry Timer  */  taskhead = task_remove(bnp->rp_connect_timer);  bnp->rp_connect_timer = NULL;}/* *   connect_process() */#define CONNECT_RETRY(bnp) { close((bnp)->rp_socket);\			     (bnp)->rp_socket = -1;\			     bgp_connect_start((bnp));\			     return; }voidconnect_process(struct rpcb *bnp){  int   myaddrlen;  int   cfd;  extern fd_set  fdmask;  cfd = recvfile(bnp->rp_sfd[0]);  FD_CLR(bnp->rp_sfd[0], &fdmask);  /* no more use            */  FD_CLR(bnp->rp_sfd[1], &fdmask);  /* <--- for safty (?) XXX */  close(bnp->rp_sfd[0]);  bnp->rp_sfd[0] = -1;  close(bnp->rp_sfd[1]);  bnp->rp_sfd[1] = -1;  wait(NULL);  if (cfd == bnp->rp_socket) {    /**  connect succeed **/    /* for Asynchronous connect */    if (((bnp->rp_mode & BGPO_IGP) && find_epeer_by_rpcb(bnp)) ||	(!(bnp->rp_mode & BGPO_IGP) && find_epeer_by_as(bnp->rp_as))) {      close(bnp->rp_socket);      bnp->rp_socket = -1;      bnp->rp_state = BGPSTATE_IDLE;      if ((logflags & LOG_BGPSTATE))	syslog(LOG_NOTICE, "<%s>: BGP state shift[%s] peer: %s", __FUNCTION__,	       bgp_statestr[bnp->rp_state], bgp_peerstr(bnp));      if (!(bnp->rp_mode & BGPO_IGP)) /* EBGP */	bnp->rp_id = 0;      return;    }    /*  my address  (insufficient information, for debug) */    myaddrlen = sizeof(bnp->rp_myaddr);    if (getsockname(bnp->rp_socket,		    (struct sockaddr *)&bnp->rp_myaddr, &myaddrlen) != 0) {	    syslog(LOG_INFO, "<%s>: failed to getsockname", __FUNCTION__);	    CONNECT_RETRY(bnp);    }#ifdef ADVANCEDAPI    {      struct msghdr rcvmh;      struct cmsghdr     *cmsgp, *cm;      struct in6_pktinfo *pktinfo = NULL;      struct ifinfo      *ife;     /* ours     */       int                 off;#ifndef IPV6_RECVPKTINFO      int optlen;#endif      if ((cmsgp =	   (struct cmsghdr *)malloc(CMSG_SPACE(sizeof(struct in6_pktinfo))))	  == 0)	fatalx("<connect_process>: malloc");      memset(&rcvmh, 0, sizeof(rcvmh));      memset(cmsgp, 0, CMSG_SPACE(sizeof(struct in6_pktinfo)));      rcvmh.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));      rcvmh.msg_control = (caddr_t)cmsgp;#ifdef IPV6_RECVPKTINFO		/* new advanced API */      /* just receive ancillary data */      if (recvmsg(bnp->rp_socket, &rcvmh, 0) < 0)	fatal("<connect_process>: recvmsg");#else  /* old advanced API */      optlen  = CMSG_SPACE(sizeof(struct in6_pktinfo));      if (getsockopt(bnp->rp_socket, IPPROTO_IPV6, IPV6_PKTOPTIONS,		     (void *)cmsgp, &optlen))	fatal("<connect_process>: getsockopt(IPV6_PKTOPTIONS)");#endif      for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&rcvmh); cm;	   cm = (struct cmsghdr *)CMSG_NXTHDR(&rcvmh, cm)) {	if (cm->cmsg_level != IPPROTO_IPV6 ||	    (cm->cmsg_type != IPV6_PKTINFO) ||	    cm->cmsg_len != CMSG_LEN(sizeof(struct in6_pktinfo)))	  continue;	pktinfo = (struct in6_pktinfo *)CMSG_DATA(cm);	break;      }      if (pktinfo == NULL)	fatalx("<connect_process>: can't get connecting interface");      if (!(ife = find_if_by_index(pktinfo->ipi6_ifindex)))	fatalx("<connect_process>: find_if_by_index: Unknown I/F");      free(cmsgp);		/* XXX: ugly, but important */      if (bnp->rp_mode & BGPO_IFSTATIC) {	if (bnp->rp_ife != ife)	  CONNECT_RETRY(bnp);      } else {	bnp->rp_ife = ife; /* overwrite */      }      off = 0;#ifdef IPV6_RECVPKTINFO      if (setsockopt(bnp->rp_socket, IPPROTO_IPV6, IPV6_RECVPKTINFO,		     &off, sizeof(off)) < 0) {	      syslog(LOG_INFO, "<%s>: failed to setsockopt(IPV6_RECVPKTINFO)",		     __FUNCTION__);	      CONNECT_RETRY(bnp);      }#else  /* old adv. API */      if (setsockopt(bnp->rp_socket, IPPROTO_IPV6, IPV6_PKTINFO,		     &off, sizeof(off)) < 0) {	      syslog(LOG_INFO, "<%s>: failed to setsockopt(IPV6_PKTINFO)",		     __FUNCTION__);	      CONNECT_RETRY(bnp);      }#endif     }#else  /* ! ADVANCEDAPI */    {      struct ifinfo *ife;      if (!(ife = find_if_by_addr(&bnp->rp_myaddr.sin6_addr)))	fatalx("<connect_process>: find_if_by_addr: Unknown Address");      if (bnp->rp_mode & BGPO_IFSTATIC) {	if (bnp->rp_ife != ife)	  CONNECT_RETRY(bnp);      } else {	bnp->rp_ife = ife; /* overwrite */      }    }#endif /* ADVANCEDAPI */    bgp_send_open(bnp);    return;  } else { /**  connect() failed.  **/    CONNECT_RETRY(bnp);  }}#undef CONNECT_RETRY/* Marker (16-octets to be all 1) */#define BGP_MARKER_CHECK  for (i = 0; i < BGP_HEADER_MARKER_LEN; i++) { \	   if (bh->bh_marker[i] != 0xff) {\	    bgp_notify(bnp, BGP_ERR_HEADER, BGP_ERRHDR_UNSYNC, 0, NULL);\	    return;\	   };\          }/* *    bgp_process_open()

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -