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

📄 main.c

📁 同时支持IPv4和IPv6的BGP协议实现
💻 C
字号:
/* * 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"#include "parse.h"#include "ospf.h"#include "cfparse.h"int confcheck = 0;		/* configuration check only */int              rtsock;       /* the routing socket               */pid_t            pid;fd_set           fdmask;fd_set           currentmask;struct ifinfo   *ifentry;      /* interface list                   */struct rt_entry *aggregations; /* aggregate-generated routes       */task            *taskhead;byte             bgpyes, ripyes, ospfyes;unsigned long logflags;time_t bgpd_start_time;time_t last_rip_dump;#define  PIDFILENAME  "/var/run/bgpd.pid"#define CONFFILENAME  "/usr/local/v6/etc/bgpd.conf"extern void bgpd_dump_file();static int do_dump;static void bgpd_set_dump_file();/* *  Main */ intmain(argc, argv)     int    argc;     char **argv;{  struct rpcb *bnp;  FILE        *pfp;  int          foreground = 0;  int          ch;  char *conf = NULL;  extern struct rpcb *bgb;  extern task        *taskhead;  extern byte         IamRR;  extern u_int32_t    clusterId;  /* Global var initialize */  bgpyes    = ripyes  = 0;  ospfyes = 0;             /* XXX: experimental */  bgb = NULL;  taskhead  = NULL;  IamRR     = 0;  clusterId = 0;  aggregations = NULL;  FD_ZERO(&fdmask);    /* get options */  while ((ch = getopt(argc, argv, "Cc:f")) != -1){    switch (ch){    case 'C':      confcheck++;      break;    case 'c':      conf = optarg;      break;    case 'f':      foreground = 1;      break;    default:      fprintf(stderr, "usage: bgpd [-c conf_file] [-f]\n");      fprintf(stderr, "\t-f: Run foreground.\n");      fprintf(stderr, "\t-c: Specify the configuration file.\n");      exit(1);    }  }  if (confcheck == 0 && foreground == 0) {    if ((pid = fork()) < 0){      fprintf(stderr, "Cannot fork: %s\n", strerror(errno));      exit(1);    } else if (pid > 0) {      /* Parent process */      exit(0);    }  }  pid = getpid();  setitimer(ITIMER_REAL, NULL, NULL); {  char *ident;  ident = strrchr(*argv, '/');  if (!ident)    ident = *argv;  else    ident++;  openlog(ident, LOG_NDELAY|LOG_PID, LOG_DAEMON); }  syslog(LOG_NOTICE, "IPv6 routing started, pid %d ******************", pid);  (void)time(&bgpd_start_time);  /* write PID file */  if (confcheck == 0) {     pfp = fopen(PIDFILENAME, "w");    if (pfp == NULL) {      fprintf(stderr, "Cannot open PID file: %s. Exit.\n", strerror(errno));      exit(1);    }    fprintf(pfp, "%d\n", pid);    fclose(pfp);  }  loconfig("lo0");  ifconfig();  if (confcheck == 0)    krt_init();#ifndef WITHOUT_LEX_YACC  if (cfparse(1, conf ? conf : CONFFILENAME))    exit(1);  if (confcheck)    exit(0);  /* initialization after parsing configuration */  install_static();  if (ripyes) {    rip_sockinit();    rip_import_init();  }  if (bgpyes) {    bgp_paraminit();    bgp_sockinit();  }#else  conf_check(conf ? conf : CONFFILENAME);#endif  aggr_ifinit();  if (signal(SIGALRM, (void *)alarm_handler) < 0)    fatal("<main>: SIGALRM");  if (signal(SIGPIPE, (void *)pipe_handler) < 0)    fatal("<main>: SIGPIPE");  if (signal(SIGINT, (void *)bgpdexit) < 0)    fatal("<main>: SIGINT");  if (signal(SIGTERM, (void *)bgpdexit) < 0)    fatal("<main>: SIGTERM");  if (signal(SIGUSR1, (void *)bgpd_set_dump_file) < 0)    fatal("<main>: USR1");  if (bgpyes) {    ibgpconfig();   /* setup [rfc1966] */    bnp = bgb;    while(bnp) {      if (!(bnp->rp_mode & BGPO_PASSIVE))	bgp_connect_start(bnp);                /* "bnp" won't be lost */      if ((bnp = bnp->rp_next) == bgb)	break;    }  }  if (ripyes)    rip_query_dump();  if (ospfyes)    ospf_init();    main_listen_accept();  /* NOT REACHED */  return 1;}/* * *  main_listen_accept() - process an incoming connection. *                          called by main() only once. */voidmain_listen_accept(){  int    s;                          /* accepted descriptor    */  struct sockaddr_in6 fromaddr;      /* accepted address       */  int                 fromaddrlen;  int                   myaddrlen;   /* length of my address   */  struct rpcb          *bnp;#ifndef IPV6_RECVPKTINFO  int optlen;#endif  extern struct rpcb *bgb;  extern int          bgpsock, ripsock, ospfsock;  memset(&fromaddr, 0, sizeof(fromaddr));  while (1) {                                            /* outer */    sigset_t set, oset;    struct ifinfo *ife_dummy = NULL; /* XXX */    while (1) {      FD_COPY(&fdmask, &currentmask);      if (do_dump) {		/* SIGUSR1 */	      do_dump = 0;	      bgpd_dump_file();      }      if (select(FD_SETSIZE, &currentmask, NULL,NULL,NULL) < 0) {	if (errno == EINTR) {	  /* interrupted by SIGALRM */	} else {	  fatal("<main_listen_accept>: select");	}      } else {	/* an Event occurs.  break inner while */	break;      }    }    sigemptyset(&oset);    sigemptyset(&set);    sigaddset(&set, SIGALRM);    if ((sigprocmask(SIG_BLOCK, &set, &oset)) != 0)      fatal("<main_listen_accept>: sigprocmask");    /*     *   Passive open BGP connection:  accept()     */    if (bgpyes &&	FD_ISSET(bgpsock, &currentmask)) {      int alen;      /* purge ancillary data (if any) on the listening socket */      if (ioctl(bgpsock, FIONREAD, &alen) <0)/* XXX is there a smarter way? */	fatal("<main_listen_accept>: ioctl(FIONREAD)");      if (alen > 0) {	      if (read(bgpsock, NULL, 0) < 0)		      fatal("<main_listen_accept>: read on the listening socket");	      /* XXX: make sure to purge all ancillary data before accepting */	      continue;      }      /*       * Accept the BGP connection.       */      fromaddrlen = sizeof(fromaddr);      if ((s = accept(bgpsock,		      (struct sockaddr *)&fromaddr,		      (int *)&fromaddrlen)) < 0) {	fatal("<main_listen_accept>: accept");      }      bnp = bgp_new_peer();      bnp->rp_mode   |= BGPO_PASSIVE;      bnp->rp_socket  = s;      bnp->rp_addr    = fromaddr;          /* copy */  /* passive */      IFLOG(LOG_BGPINPUT)	      syslog(LOG_DEBUG, "<main_listen_accept>: %s now accepted",		     bgp_peerstr(bnp));      if (IN6_IS_ADDR_LINKLOCAL(&fromaddr.sin6_addr))	bnp->rp_laddr = fromaddr.sin6_addr; /* copy */      else	bnp->rp_gaddr = fromaddr.sin6_addr; /* ummh */      /*  my address  (insufficient information) */      myaddrlen = sizeof(bnp->rp_myaddr);      if (getsockname(bnp->rp_socket,		      (struct sockaddr *)&bnp->rp_myaddr, &myaddrlen) != 0)	fatal("<main_listen_accept>: getsockname");      if (in6_is_addr_onlink(&fromaddr.sin6_addr, &ife_dummy))	bnp->rp_mode |= BGPO_ONLINK;	            {#ifdef ADVANCEDAPI	struct msghdr rcvmh;	struct cmsghdr     *cmsgp, *cm;	struct in6_pktinfo *pktinfo = NULL;#endif	/* set receive interface if the connection is on-link */#ifdef ADVANCEDAPI	/*	 * XXX: we can't use a static buffer, since CMSG_SPACE might be a	 * function.	 */	if ((cmsgp =	     (struct cmsghdr *)malloc(CMSG_SPACE(sizeof(struct in6_pktinfo))))	    == 0)	  fatalx("<main_listen_accept>: 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("<main_listen_accept>: 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("<main_listen_accept>: 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("<main_listen_accept>: can't get accepted interface");	if ((bnp->rp_ife = find_if_by_index(pktinfo->ipi6_ifindex)) == NULL)	  fatalx("<main_listen_accept>: find_if_by_index: Unknown I/F");	IFLOG(LOG_BGPINPUT)	  syslog(LOG_DEBUG,		 "<%s>: accepted a BGP connection from %s to %s on %s",		 __FUNCTION__, ip6str2(&fromaddr),		 ip6str(&pktinfo->ipi6_addr, 0),		 bnp->rp_ife->ifi_ifn->if_name);	free(cmsgp);		/* XXX: ugly, but important */#else  /* !ADVANCEDAPI */      if ((bnp->rp_ife = find_if_by_addr(&bnp->rp_myaddr.sin6_addr)) == NULL)	fatalx("<main_listen_accept>: find_if_by_addr Unknown I/F");#endif /* ADVANCEDAPI */      }      insque(bnp, bgb);      bgp_send_open(bnp);    }   /* End of "bgpsock" */    /* Check BGP external-links of their discriptors */    if (bgpyes) {      bnp = bgb;      while(bnp) {	if (bnp->rp_socket != -1) {        /* Skip which is idling */	  if (FD_ISSET(bnp->rp_socket, &currentmask)) {	    FD_CLR(bnp->rp_socket, &currentmask);	    bgp_input(bnp);	    if ((bnp = bgb) ==  NULL)  /* peers-queue maybe changed */	      break;	    else	      continue;	  }	}	if ((bnp = bnp->rp_next) == bgb)	  break;      }    }    /* Check RIP  */    if (ripyes) {      if (FD_ISSET(ripsock, &currentmask))	rip_input();    }    /* Check OSPF  */    if (ospfyes) {      if (FD_ISSET(ospfsock, &currentmask))	ospf_input();    }    /* check parent/child pipe... for connect() */    if (bgpyes) {      bnp = bgb;      while(bnp) {	if (bnp->rp_sfd[0] != -1) {        /* Skip which is no use */	  if (FD_ISSET(bnp->rp_sfd[0], &currentmask)) {	    FD_CLR(bnp->rp_sfd[0], &currentmask);	    connect_process(bnp);	    if ((bnp = bgb) ==  NULL)  /* peers-queue maybe changed */	      break;	    else	      continue;	  }	}	if ((bnp = bnp->rp_next) == bgb)	  break;      }    }    if ((sigprocmask(SIG_UNBLOCK, &set, &oset)) != 0)      fatal("<main_listen_accept>: sigprocmask");  }  /* while (outer) */  fatalx("<main_listen_accept>: invalidly reached.");}/* *   alarm_handler() */void alarm_handler(){  switch (taskhead->tsk_timename) {  case BGP_CONNECT_TIMER:    switch (taskhead->tsk_bgp->rp_state) {    case BGPSTATE_CONNECT : case BGPSTATE_ACTIVE :       connect_try(taskhead->tsk_bgp);      break;    default:      fatalx("<alarm_handler>: unexpected bgp-status");      break;    }    break;  case BGP_HOLD_TIMER:    bgp_holdtimer_expired(taskhead);    break;  case BGP_KEEPALIVE_TIMER:    switch (taskhead->tsk_bgp->rp_state) {    case BGPSTATE_OPENCONFIRM : case BGPSTATE_ESTABLISHED :       bgp_send_keepalive(taskhead->tsk_bgp);      break;    default:      fatalx("<alarm_handler>: unexpected bgp-status");      break;    }    break;  case RIP_DUMP_TIMER:    (void)time(&last_rip_dump);    rip_dump();    break;  case RIP_LIFE_TIMER:    rip_life_expired();    break;  case RIP_GARBAGE_TIMER:    rip_garbage_expired();    break;  case OSPF_HELLO_TIMER:    ospf_hello();    break;  default:    fatalx("<alarm_handler>: invalid timer name");  }}/* *  pipe_handler() */void pipe_handler(){	IFLOG(LOG_BGPCONNECT)		syslog(LOG_DEBUG, "SIGPIPE received.");  return;}/* * bgpd_set_dump_file() * signal handler for SIGUSR1. Set  */static voidbgpd_set_dump_file(){	do_dump = 1;}/* *  fatal() */voidfatal(msg)        char    *msg;{        perror(msg);        syslog(LOG_ERR, "%s: %s", msg, strerror(errno));        bgpdexit();}voidfatalx(msg)	char *msg;{	fprintf(stderr, "%s\n", msg);	syslog(LOG_ERR, "%s", msg);	bgpdexit();}/* debugging log  */voiddperror(msg)        char    *msg;{        perror(msg);        syslog(LOG_ERR, "%s: %s", msg, strerror(errno));}/* *   bgpdexit() */voidbgpdexit(){  struct rpcb         *bnp;  struct ripif        *ripif;  struct ifinfo *ife;  extern int           bgpsock;  extern struct rpcb  *bgb;  extern struct ripif *ripifs;  alarm(0);  /* turns off any scheduled alarm. */  if (bgpyes) {    bnp = bgb;    while(bnp) {      bgp_send_notification(bnp, BGP_CEASE, BGP_ERR_UNSPEC, 0, NULL);      bgp_flush(bnp);      if ((bnp = bnp->rp_next) == bgb)	break;    }    close(bgpsock);  }  if (ripyes) {    ripif = ripifs;    while(ripif) {      while(ripif->rip_adj_ribs_in)	rip_erase_rte(ripif->rip_adj_ribs_in);      if ((ripif = ripif->rip_next) == ripifs)	break;    }  }  /* removed all static routes */  ife = ifentry;  while(ife) {	  struct rt_entry *irte;	  irte = ife->ifi_rte;	  while(irte) {		  if (irte->rt_flags & (RTF_BGPDIFSTATIC | RTF_BGPDGWSTATIC))			  (void)delroute(irte, NULL);		  if ((irte = irte->rt_next) == ife->ifi_rte)			  break;	  }	  if ((ife = ife->ifi_next) == ifentry)		  break;  }  terminate();}/* *   terminate() */voidterminate() {  close(rtsock);  syslog(LOG_NOTICE, "IPv6 routing Terminated *************************");  closelog();  unlink(PIDFILENAME);  exit(1);}

⌨️ 快捷键说明

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