📄 ospf.c
字号:
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 + -