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

📄 ospf.c

📁 同时支持IPv4和IPv6的BGP协议实现
💻 C
📖 第 1 页 / 共 2 页
字号:
  len = 0;  if ((len = recvmsg(ospfsock, &rmsghdr, 0)) < 0)    fatal("<ospf_input>: recvmsg");  if (IN6_IS_ADDR_LINKLOCAL(&fsock.sin6_addr))    CLEAR_IN6_LINKLOCAL_IFINDEX(&fsock.sin6_addr);  /* for safty */#ifdef ADVANCEDAPI  for (ch = CMSG_FIRSTHDR(&rmsghdr);ch; ch = CMSG_NXTHDR(&rmsghdr, ch)) {    if (ch->cmsg_level == IPPROTO_IPV6 &&	ch->cmsg_type  == IPV6_PKTINFO &&	ch->cmsg_len   == CMSG_LEN(sizeof(struct in6_pktinfo))) {      rpktinfo = (struct in6_pktinfo *)CMSG_DATA(ch);    }    if (ch->cmsg_level == IPPROTO_IPV6 &&	ch->cmsg_type  == IPV6_HOPLIMIT &&     /* may not be supported */	ch->cmsg_len   == CMSG_LEN(sizeof(int))) {      rhoplimit = (int *)CMSG_DATA(ch);    }  }  if (rpktinfo == NULL) {    fatalx("<ospf_input>: Can't get received interface");    return;  }#else  /* for older hydranger */  {      struct ifinfo *ife;      static struct in6_pktinfo rrpktinfo;      if ((ife = find_if_by_addr(&fsock.sin6_addr)) == NULL)	  fatalx("<ospf_input>: find_if_by_addr");      rrpktinfo.ipi6_ifindex = ife->ifi_ifn->if_index;      rpktinfo = &rrpktinfo;  }#endif /* ADVANCEDAPI */#ifdef DEBUG_OSPF  syslog(LOG_DEBUG, "OSPFv3 RECV %s -> %s(%s)",	 inet_ntop(AF_INET6, &fsock.sin6_addr, in6txt, INET6_ADDRSTRLEN),	 inet_ntop(AF_INET6, &rpktinfo->ipi6_addr, myin6txt, INET6_ADDRSTRLEN),	 if_indextoname(rpktinfo->ipi6_ifindex, ifname));#endif  /* Locally originated packets should not be passed on to OSPF.     That is, the source IPv6 adddress should be examined to make sure     this is not a multicast packet that the router itself generated.  */  ife = ifentry;  while(ife) {    if (IN6_ARE_ADDR_EQUAL(&ife->ifi_laddr, &fsock.sin6_addr)) {      return;    }    if ((ife = ife->ifi_next) == ifentry)      break; /* while */  }  /* the interface it was received on [OSPF-v2 pp.51] */  if ((ife = find_if_by_index((u_int)rpktinfo->ipi6_ifindex)) == NULL) {    syslog(LOG_ERR,	   "<ospf_input>: OSPFv3 received at Unknown I/F %d (ignored)",	   rpktinfo->ipi6_ifindex);    return;  }  if (len < sizeof(struct ip6_hdr) + sizeof(struct ospfhdr))    return;  oh = (struct ospfhdr *)(ospfbuf + IPV6_HDRLEN);#ifdef DEBUG_OSPF  syslog(LOG_DEBUG, "OSPFv3 RECV RouterID: %s  Area: %s  Checksum:0x%x",	 inet_ntop(AF_INET, &oh->ospfh_rtr_id,  rtrid,  INET_ADDRSTRLEN),	 inet_ntop(AF_INET, &oh->ospfh_area_id, areaid, INET_ADDRSTRLEN),	 oh->ospfh_cksum);#endif  memset(&phdr, 0, sizeof(phdr));  phdr.ph6_src   = fsock.sin6_addr;  phdr.ph6_dst   = rpktinfo->ipi6_addr;  phdr.ph6_uplen = len - IPV6_HDRLEN;  phdr.ph6_nxt   = IPPROTO_OSPF;  cksum          = ntohs(oh->ospfh_cksum);  /* Before computing the checksum, the checksum field in the OSPF packet     header is set to 0. [Page 56] */  oh->ospfh_cksum = 0;  if (cksum != ip6_cksum(&phdr, (u_char *)oh)) {    syslog(LOG_NOTICE, "OSPFv3 RECV invalid Checksum: rcvd=0x%x, calcd=0x%x",	   cksum, ip6_cksum(&phdr, ospfbuf));    return;  }  /*  The version number field must specify protocol version  3. */  if (oh->ospfh_vers != OSPF_VERSION_3) {    syslog(LOG_ERR, "<ospf_input>: Unknown OSPF version %d", oh->ospfh_vers);    return;  }  /* The Area ID found in the OSPF header must be verified. */  ol = (struct ospflink *)ife->ifi_rtpinfo[RTPROTO_OSPF];  if (ol->ol_area->ar_id != oh->ospfh_area_id)    return;  if (ntohs(oh->ospfh_length) > len)    return;  switch (oh->ospfh_type) {         /* received type */  case OSPF_PKT_HELLO:#ifdef DEBUG_OSPF    syslog(LOG_DEBUG, "OSPFv3 RECV %s  Len: %d",	   ospf_msgstr[oh->ospfh_type], ntohs(oh->ospfh_length));#endif    ospf_process_hello(oh, ife);    break;    /* All other packet types are sent/received only on adjacencies.       [OSPFv2 pp.53] */  case OSPF_PKT_DD:#ifdef DEBUG_OSPF    syslog(LOG_DEBUG, "OSPFv3 RECV %s Len: %d",	   ospf_msgstr[oh->ospfh_type], ntohs(oh->ospfh_length));#endif    if ((nbr = rpcblookup(ol->ol_nbrs, oh->ospfh_rtr_id)) == NULL)      return;    ospf_process_dd(oh, nbr);    break;    default:    syslog(LOG_ERR,	   "<ospf_input>: Unknow OSPF type %d", oh->ospfh_type);    break;  }  return; }/* *   ospf_process_hello() */voidospf_process_hello(oh, ife)     struct ospfhdr *oh;     struct ifinfo  *ife;{  struct rpcb        *nbr;  struct ospflink    *ol;  struct ospfhdr     *ospfh;  struct ospf_db_hdr *ospfdd;  struct in6_pktinfo  spktinfo;  int len;  /* sending OSPF packet length */  extern u_int32_t    bgpIdentifier;  ol = (struct ospflink *)ife->ifi_rtpinfo[RTPROTO_OSPF];  if ((nbr = rpcblookup(ol->ol_nbrs, oh->ospfh_rtr_id)) == NULL) {    MALLOC(nbr, struct rpcb);    nbr->rp_ife  = ife;    nbr->rp_id   = oh->ospfh_rtr_id;    if (ol->ol_nbrs)      insque(nbr, ol->ol_nbrs);    else {      nbr->rp_next = nbr->rp_prev = nbr;      ol->ol_nbrs  = nbr;    }    memset(&ospfpkt, 0, OSPF_MAXPKT);    ospfh   = (struct ospfhdr *)ospfpkt;    ospfh->ospfh_vers   = OSPF_VERSION_3;    ospfh->ospfh_type   = OSPF_PKT_DD;    ospfh->ospfh_rtr_id = bgpIdentifier;    ospfdd = &ospfh->ospfh_database;    ospfdd->od_ifmtu  = htons(MINMTU);    ospfdd->od_i_m_ms |= bit_I;    ospfdd->od_i_m_ms |= bit_MS;    len = sizeof(struct ospfhdr) - sizeof(union ospf_types)          + sizeof(struct ospf_db_hdr);    len += ospf_make_dump((u_char *)(ospfdd + 1));  /* give buffer */    ospfh->ospfh_length    = htons(len);    spktinfo.ipi6_addr    = ife->ifi_laddr;  /* copy */    spktinfo.ipi6_ifindex = ife->ifi_ifn->if_index;    ospf_sendmsg(&fsock,       /* sender's address    */		 &spktinfo,    /* source address, I/F */		 ntohs(ospfh->ospfh_length));  }  /*  End of ospf_process_hello()  */}/* *   ospf_process_dd() *      The incoming Database Description Packet has already been associated  *      with a neighbor and receiving interface by the generic input packet *      processing. */voidospf_process_dd(oh, nbr)     struct ospfhdr *oh;     struct rpcb    *nbr;{  struct ospflink      *ol;  struct ospf_db_hdr   *ospfdd;  struct lsahdr        *lsahdr;  struct ospf_prfx     *opx;  struct rt_entry      *uprte;  int                   len;   /* left       */  extern struct ifinfo *ifentry;#ifdef DEBUG_OSPF  char                in6txt[INET6_ADDRSTRLEN];  memset(in6txt, 0, INET_ADDRSTRLEN);#endif  len = htons(oh->ospfh_length) -         (sizeof(struct ospfhdr) - sizeof(union ospf_types)          + sizeof(struct ospf_db_hdr));  /* now len is of unread LSAs */    ol = (struct ospflink *)(nbr->rp_ife->ifi_rtpinfo[RTPROTO_OSPF]);  ospfdd = &oh->ospfh_database;  if (len < sizeof(struct lsahdr))    return;  lsahdr = (struct lsahdr *)(ospfdd + 1);  while(lsahdr) {  /* all LSAs */    u_int16_t lstype;    if (lsahdr->lsa_adv_rtr == nbr->rp_id) { /* off-link LSA not implemented */      lstype = ntohs(lsahdr->lsa_lstype) & ~bit_U & ~bit_S2 & ~bit_S1;       switch(lstype) {      case LS_PREFIX: {	struct iap_lsa   *iap;	int num;    /* # prefixes */	if ((ntohs(lsahdr->lsa_length) <	     sizeof(struct lsahdr) + sizeof(struct iap_lsa)) ||	    (ntohs(lsahdr->lsa_length) > len))	  return;   /* Bad Length */ 	len -= sizeof(struct lsahdr) + sizeof(struct iap_lsa);	iap = (struct iap_lsa *)(lsahdr + 1);	opx = (struct ospf_prfx *)(iap + 1);	for (num = ntohs(iap->iap_num) ; num > 0 ; num--) {	  struct rt_entry *rte, *orte;	  struct ripinfo6 *np;	  struct ifinfo   *ife;	  int              poctets = POCTETS(opx->opx_plen);	  int              plen4w; /* 32-bit (4-byte) word boudary */	  if (len < sizeof(struct ospf_prfx) + poctets)	    return;	  MALLOC(rte, struct rt_entry);	  /*   XXX: NOT SPF at all.  */	  rte->rt_gw    = fsock.sin6_addr; /* sender's */	  rte->rt_flags = RTF_UP|RTF_GATEWAY;	  np = &rte->rt_ripinfo;	  memcpy(&np->rip6_dest, (u_char *)(opx+1), poctets);	  np->rip6_plen   = opx->opx_plen;	  np->rip6_metric = (u_char)ntohs(opx->opx_metric);	  mask_nclear(&np->rip6_dest, np->rip6_plen);	  rte->rt_proto.rtp_type = RTPROTO_OSPF;	  rte->rt_proto.rtp_ospf = nbr;#ifdef DEBUG_OSPF	  syslog(LOG_DEBUG, "OSPFv3 RECV\t%s/%d (%d)",		 inet_ntop(AF_INET6, &np->rip6_dest, in6txt, INET6_ADDRSTRLEN),		 np->rip6_plen, np->rip6_metric);#endif	  /**  check I/F addrs  **/	  /**  check I/F routes **/	  ife = ifentry;	  orte = NULL;	  while (ife) {	    if ((orte = find_rte(rte, ife->ifi_rte)))	      break;	    if ((ife = ife->ifi_next) == ifentry)	      break;	  }	  if (orte != NULL) {  /* I/F direct route (most preferable) */#ifdef DEBUG_OSPF	    syslog(LOG_DEBUG,		   "<ospf_process_dd>: I/F direct route cannot overwritten");#endif	    rte = NULL;	  }	  if (find_rte(rte, nbr->rp_adj_ribs_in))	    rte = NULL;	  if (rte) {	    uprte = igp_enable_rte(rte);   /* copied */	    free(uprte); /* XXX: ad-hoc */	  }	  plen4w = poctets%4  ? (poctets/4 + 1) * 4 :  poctets;	  len -= (sizeof(struct ospf_prfx) + poctets);	  opx = (struct ospf_prfx *)((u_char *)(opx + 1) + plen4w);	}      }      default:	break;      }    }  }  /*  End of ospf_process_dd()  */}/* *  ospf_make_dump() *      RETURN VALUES: length of buf */intospf_make_dump(buf)     u_char *buf;{  struct ifinfo    *ife;  struct lsahdr    *lsahdr;  struct iap_lsa   *iap;  struct ospf_prfx *opx;  int               len;     /* length of the LSA includes LSA header */  int               num = 0;  extern u_int32_t      bgpIdentifier;  extern struct ifinfo *ifentry;  lsahdr = (struct lsahdr *)buf;  /*  Intra-Area-Prefix-LSAs:  LS type = 9  */  /*         (for attached network)         */  lsahdr->lsa_age     = 0;        /* [OSPFv6 page.24]; newly (re)originated */  lsahdr->lsa_lstype  = htons(LS_PREFIX | bit_S1); /* area scope            */  lsahdr->lsa_lsid    = htons(ls_sequence);        /* or something          */  lsahdr->lsa_adv_rtr = bgpIdentifier;             /* Originated Router ID  */  lsahdr->lsa_seq     = htons(ls_sequence);  ls_sequence++;  iap = (struct iap_lsa *)(lsahdr + 1);  iap->iap_ref_lstype  = htons(LS_RTR | bit_S1);   /* router-LSA reference  */  iap->iap_ref_lsid    = 0;  iap->iap_ref_adv_rtr = bgpIdentifier;  opx = (struct ospf_prfx *)(iap + 1);  ife = ifentry;  while(ife) {    struct rt_entry  *rte;    rte = ife->ifi_rte;  /* I/F direct RTEs */    while(rte) {      struct ripinfo6 *np      = &rte->rt_ripinfo;      int              poctets = POCTETS(np->rip6_plen);      int              plen4w; /* 32-bit (4-byte) word boudary */      opx->opx_plen   = np->rip6_plen;      opx->opx_opts   = 0;      opx->opx_metric = htons(np->rip6_metric + 1);      memcpy(opx + 1,  &np->rip6_dest, poctets);      plen4w = poctets%4  ? (poctets/4 + 1) * 4 :  poctets;      opx = (struct ospf_prfx *)((u_char *)(opx + 1)  +  plen4w);      num++;      if ((rte = rte->rt_next) == ife->ifi_rte)	break;    }/* (rte) */        if ((ife = ife->ifi_next) == ifentry)      break; /* (ife) */  }  iap->iap_num = htons(num);  len =  (u_char *)opx - buf;  lsahdr->lsa_length  = htons(len);  /**  LS checksum  **/  lsahdr->lsa_lscksum = htons(lsa_cksum(buf, len));  return len;  /* End of ospf_make_dump()  */}u_int16_tlsa_cksum(lsa, len)     u_char *lsa;     int     len;{  u_int32_t sum = 0;  while(len > 1) {    sum += *((u_int16_t *) lsa)++;    if (sum & 0x80000000)      sum = (sum & 0xffff) + (sum >> 16);    len -= 2;  }  if (len)    sum += (u_int16_t)*(u_char *)lsa;  while (sum >> 16)    sum = (sum & 0xffff) + (sum >> 16);  return ~sum;}

⌨️ 快捷键说明

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