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

📄 bgp.c

📁 同时支持IPv4和IPv6的BGP协议实现
💻 C
📖 第 1 页 / 共 5 页
字号:
 *        DESCRIPTION: process received OPEN msg. */voidbgp_process_open(struct rpcb *bnp){  int             i, k;       /*  tracer     */  u_int16_t       rcvas, rcvht, negoht;  u_int32_t       rcvid;      /*  net-order  */  u_int8_t        optlen;  struct rpcb    *ep = NULL;  /*    eBGP     */  struct rpcb    *ip = NULL;  /*    iBGP     */  struct rpcb    *p  = NULL;  struct bgphdr  *bh;  struct timeval  t;          /* calculation */  task           *tsk;  extern task *taskhead;    bh = (struct bgphdr *)bnp->rp_inpkt;  BGP_MARKER_CHECK;  if (bnp->rp_state != BGPSTATE_OPENSENT) {    bgp_notify(bnp, BGP_ERR_FSM, BGP_ERR_UNSPEC, 0, NULL);    return;  }  /***  OPEN Message Format  ***/  i = BGP_HEADER_LEN;  /* Version (1-octet)    */  /* If the version number contained in the Version field of the received     OPEN message is not supported, then the Error Subcode is set to     Unsupported Version Number.  The Data field is a 2-octet unsigned     integer, which indicates the largest locally supported version number     less than the version the remote BGP peer bid (as indicated in the     received OPEN message). */  if (bnp->rp_inpkt[i++] != BGP_VERSION_4) {    u_int16_t version = BGP_VERSION_4;    version = htons(version);    bgp_notify(bnp, BGP_ERR_OPEN, BGP_ERROPN_VERSION, 2, (byte *)&version);    return;  }  /* My Autonomous System (2-octet) */  rcvas = ntohs(*(u_short *)&bnp->rp_inpkt[i]);  i += 2;  if ((logflags & LOG_BGPINPUT))    syslog(LOG_DEBUG,	   "BGP+ RECV\t\tAutonomous System = %d", rcvas);  /* Hold Time            (2-octet) */  rcvht = ntohs(*(u_short *)&bnp->rp_inpkt[i]);  if ( !HOLDTIME_ISCORRECT(rcvht) ) {    bgp_notify(bnp, BGP_ERR_OPEN, BGP_ERROPN_BADHOLDTIME, 0, NULL);    return;  };  i += 2;  /* BGP Identifier       (4-octet) */  rcvid = *(u_long *)&bnp->rp_inpkt[i];  if ((logflags & LOG_BGPINPUT))    syslog(LOG_DEBUG,	   "BGP+ RECV\t\tBGP Identifier = %s",	   inet_ntoa(*(struct in_addr *)&rcvid));  if (rcvid == 0) {    bgp_notify(bnp, BGP_ERR_OPEN, BGP_ERROPN_BGPID, 0, NULL);/* Bad BGPID */    return;  };  i += 4;  /* If the Autonomous System field of the OPEN message is unacceptable,     then the Error Subcode is set to Bad Peer AS.  The determination of     acceptable Autonomous System numbers is outside the scope of this     protocol.                   (See section 6.2 of [I-D bgp4].)   */  if (rcvas != my_as_number) { /* EGP ? */    if (bnp->rp_mode & BGPO_PASSIVE) {      if ((ep = find_peer_by_as(rcvas))) {  /* same AS */ 	bnp->rp_as = rcvas; /* <<--- important !!! */	bnp->rp_id = rcvid;	bnp->rp_adj_ribs_out = ep->rp_adj_ribs_out;  /* fixedly */	bnp->rp_ebgp_as_prepends = ep->rp_ebgp_as_prepends;	bnp->rp_prefer = ep->rp_prefer;	bnp->rp_mode |= (ep->rp_mode & BGPO_EBGPSTATIC); /* copy EBGP static */      } else {	bgp_notify(bnp, BGP_ERR_OPEN, BGP_ERROPN_AS, 0, NULL);/*Bad Peer AS*/	return;      }    }    if (!(bnp->rp_mode & BGPO_PASSIVE)) {      if (bnp->rp_as != rcvas) {	bgp_notify(bnp, BGP_ERR_OPEN, BGP_ERROPN_AS, 0, NULL);/*Bad Peer AS*/	return;      }      if (bnp->rp_id == 0)	bnp->rp_id = rcvid;    }  } /* end of EGP */  if (rcvas == my_as_number) { /* IGP */    if (bnp->rp_mode & BGPO_PASSIVE) {      struct in6_addr     llhackaddr;      if (!IN6_IS_ADDR_UNSPECIFIED(&bnp->rp_laddr) && bnp->rp_ife) {	llhackaddr = bnp->rp_laddr;	SET_IN6_LINKLOCAL_IFINDEX(&llhackaddr, bnp->rp_ife->ifi_ifn->if_index);      }      if ((ip = rpcblookup(bgb, rcvid)) ||              /* iw97         */	  (ip = find_apeer_by_addr(&bnp->rp_gaddr)) ||   /* (1998/05/25) */	  (ip = find_apeer_by_addr(&llhackaddr)))  {  /* (1998/05/25) */	bnp->rp_as    = rcvas;	bnp->rp_id    = rcvid;	bnp->rp_mode |= BGPO_IGP;	bnp->rp_mode |= (ip->rp_mode & BGPO_IBGPSTATIC); /* copy IBGP static */	bnp->rp_adj_ribs_out = ip->rp_adj_ribs_out;    /* fixedly */      } else {	bgp_notify(bnp, BGP_ERR_OPEN, BGP_ERROPN_BGPID, 0, NULL);/*Bad BGPID*/	return;      }    }    if (!(bnp->rp_mode & BGPO_PASSIVE)) {      if ((bnp->rp_mode & BGPO_IDSTATIC) &&  /* BGP-ID wasn't configured */	  (bnp->rp_id != rcvid)) {	bgp_notify(bnp, BGP_ERR_OPEN, BGP_ERROPN_BGPID, 0, NULL);/*Bad BGPID*/	return;      } else	bnp->rp_id = rcvid;    }  } /* end of IGP */  /* Opt Parm Len         (1-octet) */  optlen = bnp->rp_inpkt[i++];  k = i;  /* Optional Parameters  (length is specified by "Opt Parm Len") */  while (i < k + optlen) {    struct bgpoptparm *bop;    bop = (struct bgpoptparm *)&bnp->rp_inpkt[i];    switch(bop->bop_type) {    case BGP_OPTPARAM_AUTH:      i += sizeof(struct bgpoptparm) + bop->bop_len;      break;      /* NO authentification is checked. */    case BGP_OPTPARAM_CAPA:      i += sizeof(struct bgpoptparm) + bop->bop_len;      break;    default:      /* If one of the Optional Parameters in the OPEN message is not	 recognized, then the Error Subcode is set to Unsupported Optional	 Parameters. [BGP-4] */      bgp_notify(bnp, BGP_ERR_OPEN, BGP_ERROPN_OPTION, 0, NULL);      return;      break;    }  }  if (i != ntohs(bh->bh_length)) {    bgp_notify(bnp, BGP_ERR_HEADER, BGP_ERRHDR_LENGTH, 0, NULL);    return;  }    p = bnp; /*  "p" initial  */  if (ep) {    if (ep->rp_id == bnp->rp_id)      switch (ep->rp_state) {      case BGPSTATE_OPENCONFIRM: case BGPSTATE_OPENSENT:	p = collision_resolv(bnp, ep);	  	if (p != bnp)  /* Local "p" is prefered to new "bnp".  And,       */	  return;      /* current "bnp" was deleted by collision_resolv() */	break;      case BGPSTATE_ESTABLISHED:	syslog(LOG_NOTICE,	       "<bgp_process_open>: Already established peer exists");	bgp_notify(bnp, BGP_CEASE, BGP_ERR_UNSPEC, 0, NULL);	return;      case BGPSTATE_IDLE: case BGPSTATE_CONNECT: case BGPSTATE_ACTIVE:	/* collision cannot be detected in these states */	p = bnp; /* Now "p" is ...      */	break;      default :	fatalx("<bgp_process_open>: not implmntd.");      };  } else {    if (ip) {      switch (ip->rp_state) {      case BGPSTATE_OPENCONFIRM: case BGPSTATE_OPENSENT:	p = collision_resolv(bnp, ip);	  	if (p != bnp)  /* Local "p" is prefered to new "bnp".  And,       */	  return;      /* current "bnp" was deleted by collision_resolv() */	break;      case BGPSTATE_ESTABLISHED:	syslog(LOG_NOTICE,	       "<bgp_process_open>: Already established peer exists");	bgp_notify(bnp, BGP_CEASE, BGP_ERR_UNSPEC, 0, NULL);	return;      case BGPSTATE_IDLE: case BGPSTATE_CONNECT: case BGPSTATE_ACTIVE:	/* collision cannot be detected in these states */	p = bnp; /* Now "p" is ...      */	break;      default :	fatalx("<bgp_process_open>: not implmntd.");      };    } else      p = bnp;  } /* End of if (ep) */  /**  HoldTime negotiation        **/  t.tv_sec  = rcvht;  t.tv_usec = 0;  /*   If the negotiated Hold Time value is zero,       then the Hold Time timer and KeepAlive timers are not started.  */  if (rcvht == 0) {    taskhead = task_remove(p->rp_hold_timer);    p->rp_hold_timer = NULL;      } else {    if (sub_timeval(&t ,&p->rp_hold_timer->tsk_timefull) > 0) {          p->rp_hold_timer->tsk_timefull.tv_sec  = rcvht;      p->rp_hold_timer->tsk_timefull.tv_usec = 0;      task_timer_update(p->rp_hold_timer);    }  }  /* NOTE: If the negotiated Hold Time is 0,            then system doesn't send/receive any KeepAlives  */  if ((negoht = p->rp_hold_timer->tsk_timefull.tv_sec) == 0) {    /* KeepAlive timer not started */  } else {    MALLOC(tsk, task);        if (taskhead) {      insque(tsk, taskhead);  /* will be sorted later by task_timer_update() */    } else {      tsk->tsk_next = tsk;      tsk->tsk_prev = tsk;      taskhead      = tsk;    }    tsk->tsk_bgp          = p;    tsk->tsk_timename     = BGP_KEEPALIVE_TIMER;    p->rp_keepalive_timer = tsk;    /* A reasonable maximum time between KEEPALIVE messages       would be one third of the Hold Time interval.  KEEPALIVE messages       MUST NOT be sent more frequently than one per second. [Page.17]*/    tsk->tsk_timefull.tv_sec  = (negoht/3 < 1) ? 1 : negoht/3;/* sec. */    tsk->tsk_timefull.tv_usec = 0;  }  bgp_send_keepalive(p);  /***  Finally, the state is changed to  OpenConfirm.   ***/  p->rp_state = BGPSTATE_OPENCONFIRM;  if ((logflags & LOG_BGPSTATE))    syslog(LOG_NOTICE, "<%s>: BGP state shift[%s] peer: %s", __FUNCTION__,	   bgp_statestr[p->rp_state], bgp_peerstr(p));}/* *    bgp_process_update() *       process received UPDATE msg. */voidbgp_process_update(struct rpcb *bnp){  int               i,j,k;       /* tracer                                */  struct bgphdr    *bh;  u_int16_t         length;      /* Length                                */  int               pa_p;        /* start point of Path Attributes        */  u_int16_t         urlen;       /* Unfeasible Routes Length              */  u_int16_t         tpalen;      /* Total Path Attributes Length          */  u_int16_t         atrlen;      /* the length of the attribute           */  u_int16_t         atrdatalen;  /* the length of the attribute data      */  byte              origin;      /* ORIGIN                                */  struct aspath    *asp;         /* AS_PATH                               */   u_int32_t         med;         /* MULTI_EXIT_DISC    (net-order)        */   u_int32_t         localpref;   /* LOCAL_PREF         (net-order)        */   int               aggregated;  /* logical                               */  u_int32_t         originatorid;/* [rfc1966]          (net-order)        */  struct clstrlist *cll;         /* [rfc1966]                             */  struct optatr *optatr = NULL;	 /* list of unrecognized attributes */  u_int8_t          nhnalen;     /* Next Hop Network Addresses Length (+) */  struct in6_addr   gnhaddr;     /* "nexthop" address                 (+) */  struct in6_addr   lnhaddr;     /* "nexthop" address                 (+) */  u_int8_t          snpanum;     /* Number of SNPAs                   (+) */  u_int8_t          snpalen;     /* Length of a SNPA                  (+) */#ifdef DRAFT_IETF_00  u_int16_t         nlrilen;     /* NLRI Length                       (+) */#endif  u_int16_t         v4nlrilen;   /* "traditional" NLRI Length             */  /* routes that may be installed and/or redistributed: */  struct rt_entry  uprtehead = {&uprtehead, &uprtehead};  /* routes that should be withdrawn: */  struct rt_entry  wdrtehead  = {&wdrtehead, &wdrtehead};  struct rt_entry  *uprte;  struct rt_entry  *wdrte;  char              in6txt[INET6_ADDRSTRLEN];  extern struct ifinfo   *ifentry;  extern struct rt_entry *aggregations;   extern char   *pa_typestr[], *origin_str[];   bitstr_t bit_decl(parsedflag, PA4_MAXTYPE);  bit_nclear(parsedflag, 0, PA4_MAXTYPE);  origin     = PATH_ORG_XX;    /* "incomplete" */  med = aggregated = originatorid = v4nlrilen = 0;  localpref  = bnp->rp_prefer; /* default      */  asp        = NULL;  cll        = NULL;  memset(&gnhaddr, 0, sizeof(gnhaddr));  memset(&lnhaddr, 0, sizeof(lnhaddr));  memset(in6txt,   0, INET6_ADDRSTRLEN);  bh = (struct bgphdr *)bnp->rp_inpkt;  /* if the OPEN message carries no Authentication Information (as an     Optional Parameter), then the Marker must be all ones. */   BGP_MARKER_CHECK;  /* Length (2-octet) */ /* was checked partially */  length = ntohs(bh->bh_length);  if (bnp->rp_state != BGPSTATE_ESTABLISHED) {    bgp_notify(bnp, BGP_ERR_FSM, BGP_ERR_UNSPEC, 0, NULL);     return;  }  /* Update Hold Timer */  task_timer_update(bnp->rp_hold_timer);  i = BGP_HEADER_LEN;  /***  UPDATE Message Format  ***/  /* Unfeasible Routes Length (2 octets) */  urlen = ntohs(*(u_short *)&bnp->rp_inpkt[i]);  i += 2 ;  /* Total Path Attribute Length (2 octets) */  tpalen = ntohs(*(u_short *)&bnp->rp_inpkt[i + urlen]);  if (urlen + tpalen + 23 > length ) {   /* Malformed Attribute List */      bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_ATTRLIST, 0, NULL);      return;  }      i += urlen;  /* IPv6 (BGP4+) ignores this. */  i += 2;      /* Total Path Attribute Length (2 octet) */  /*  Path Attributes (variable)  */  pa_p = i;  while (pa_p + tpalen > i) {    /* Malformation is detected ASAP */	  int error;	  IFLOG(LOG_BGPINPUT) {		  struct in_addr peerid;		  peerid = *(struct in_addr *)&bnp->rp_id;		  if (PA4_TYPE_VALID(bnp->rp_inpkt[i + 1]))			  syslog(LOG_DEBUG,				 "BGP+ RECV flags 0x%x code %s(%d) peerid %s:\\",				 bnp->rp_inpkt[i],				 pa_typestr[bnp->rp_inpkt[i + 1]],				 bnp->rp_inpkt[i + 1], inet_ntoa(peerid));	  }	  #define PA4_TYPE_CODE_CHECK \    { i++;\      if (bit_test(parsedflag, bnp->rp_inpkt[i]))\	{ bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_ATTRLIST, 0, NULL);\	  goto done;\	}\      bit_set(parsedflag, bnp->rp_inpkt[i]);\      i++;\    }#define PA4_LEN_PARSE \    { if (bnp->rp_inpkt[k] & PA_FLAG_EXTLEN) {\	atrdatalen = ntohs(*(u_int16_t *)&bnp->rp_inpkt[i]);\	i += 2;\      } else {\	atrdatalen = bnp->rp_inpkt[i];\	i += 1;\      }\      atrlen = i + atrdatalen - k;\      if (i + atrdatalen > pa_p + tpalen) {\	syslog(LOG_ERR, "<%s>: invalid attribute length(%d) from %s\n",\		         __FUNCTION__, atrdatalen, bgp_peerstr(bnp));\	bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_LENGTH,\		   i - k, &bnp->rp_inpkt[k]);\	goto done;\      }\    }    k = i;    switch(bnp->rp_inpkt[i + 1]) {     case  PA4_TYPE_ORIGIN:         /* ORIGIN (Type Code 1) well-known mandatory */         PA4_TYPE_CODE_CHECK;      PA4_LEN_PARSE;      /* T */      if ( (bnp->rp_inpkt[k] & PA_FLAG_OPT)     ||	  !(bnp->rp_inpkt[k] & PA_FLAG_TRANS)   ||	   (bnp->rp_inpkt[k] & PA_FLAG_PARTIAL))   {	/* Attribute Flags Error */	bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_FLAGS,		   atrlen, &bnp->rp_inpkt[k]);	goto done;      }      if (atrdatalen != PA4_LEN_ORIGIN) {       /* Attribute Length Error */	bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_LENGTH,		   atrlen, &bnp->rp_inpkt[k]);

⌨️ 快捷键说明

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