📄 ospf.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 "in6.h"#include "ospf.h"int ospfsock; /* socket for OSPF */byte ospfbuf[OSPF_BUFSIZ];byte ospfpkt[OSPF_MAXPKT]; /* should discover path MTU */struct ospfrtr *ospfrtrs; struct sockaddr_in6 ospfsin; /* AllSPFRouters ff02::5 */struct area *areas;int32_t ls_sequence; /* LS sequence number *//* * OSPF message types */char *ospf_msgstr[] = { "", "Hello", "Database Description", "Link State Request", "Link State Update", "Link State Acknowledgment"};/* * ospf_init() */voidospf_init(){ int on;#ifndef ADVANCEDAPI int hops;#endif struct ifinfo *ife; struct ipv6_mreq mreq; task *tsk; extern fd_set fdmask; extern struct ifinfo *ifentry; extern task *taskhead; memset(&ospfsin, 0, sizeof(ospfsin)); /* sockaddr_in6 */ memset(&mreq, 0, sizeof(mreq)); ls_sequence = InitialSequenceNumber; MALLOC(areas, struct area); areas->ar_next = areas->ar_prev = areas; areas->ar_id = 0; /* the backbone */ ife = ifentry; while(ife) { struct ospflink *ol; if (ife->ifi_flags & IFF_UP) { MALLOC(ol, struct ospflink); ol->ol_area = areas; /* XXX: backbone only */ ife->ifi_rtpinfo[RTPROTO_OSPF] = (caddr_t)ol; } if ((ife = ife->ifi_next) == ifentry) break; } if ((ospfsock = socket(PF_INET6, SOCK_RAW, IPPROTO_OSPF)) < 0) { fatal("<ospf_init>: socket"); } ospfsin.sin6_family = AF_INET6; ospfsin.sin6_len = sizeof(struct sockaddr_in6); /* XXX */ if (bind(ospfsock, (struct sockaddr *)&ospfsin, sizeof(ospfsin)) < 0) fatal("<ospf_init>: bind"); if (inet_pton(AF_INET6, ALLSPFROUTERS, &ospfsin.sin6_addr) != 1) fatal("<ospf_init>: inet_pton"); mreq.ipv6mr_multiaddr = ospfsin.sin6_addr; ife = ifentry; while (ife) { /* foreach I/F */ mreq.ipv6mr_interface = ife->ifi_ifn->if_index; if (setsockopt(ospfsock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) < 0) fatal("<ospf_init>: setsockopt: IPV6_JOIN_GROUP"); if ((ife = ife->ifi_next) == ifentry) break; }#ifndef ADVANCEDAPI hops = OSPF_HOPLIMIT; if (setsockopt(ospfsock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof(int)) < 0) fatal("<ospf_init>: setsockopt IPV6_MULTICAST_HOPS");#endif /* ADVANCEDAPI */ on = 0; if (setsockopt(ospfsock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &on, sizeof(on)) < 0) fatal("<ospf_init>: setsockopt IPV6_MULTICAST_LOOP");#ifdef ADVANCEDAPI on = 1;#ifdef IPV6_RECVPKTINFO if (setsockopt(ospfsock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) < 0) fatal("<ospf_init>: setsockopt(IPV6_RECVPKTINFO)");#else /* old adv. API */ if (setsockopt(ospfsock, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on)) < 0) fatal("<ospf_init>: setsockopt(IPV6_PKTINFO)");#endif on = 1;#ifdef IPV6_RECVPKTINFO if (setsockopt(ospfsock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) < 0) fatal("<ospf_init>: setsockopt(IPV6_RECVPKTINFO)");#else /* old adv. API */ if (setsockopt(ospfsock, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on)) < 0) fatal("<ospf_init>: setsockopt(IPV6_PKTINFO)");#endif #endif /* ADVANCEDAPI */ FD_SET(ospfsock, &fdmask); /* initialize */ MALLOC(tsk, task); if (taskhead) { insque(tsk, taskhead); } else { taskhead = tsk; tsk->tsk_next = tsk; tsk->tsk_prev = tsk; } tsk->tsk_timename = OSPF_HELLO_TIMER; tsk->tsk_rip = NULL; /* XXX */ tsk->tsk_timefull.tv_sec = 1; /* immediately */ tsk->tsk_timefull.tv_usec = 0; task_timer_update(tsk); /* End of ospf_init() */}/* * ospf_hello() */voidospf_hello() { struct ifinfo *ife; struct in6_pktinfo spktinfo; struct ospfhdr *ospfh; struct ospf_hello_hdr *ospfhello; extern u_int32_t bgpIdentifier; extern struct ifinfo *ifentry; extern task *taskhead; memset(&ospfpkt, 0, OSPF_MAXPKT); ospfh = (struct ospfhdr *)ospfpkt; /* outgoing OSPF header */ ospfh->ospfh_vers = OSPF_VERSION_3; ospfh->ospfh_type = OSPF_PKT_HELLO; ospfh->ospfh_rtr_id = bgpIdentifier; ospfhello = &ospfh->ospfh_hello; ospfhello->oh_helloint = htons(OSPF_T_HELLOINTERVAL); ospfhello->oh_deadint = htons(OSPF_T_HELLOINTERVAL * 4); /* XXX: ad-hoc */ ife = ifentry; /* global */ while(ife) { /* On all OSPF interfaces except virtual links, OSPF packets are sent using the interface's associated link- local unicast address as source. */ spktinfo.ipi6_addr = ife->ifi_laddr; /* copy */ spktinfo.ipi6_ifindex = ife->ifi_ifn->if_index; ospfhello->oh_if_id = GET_IN6_IF_ID_OSPF(&ife->ifi_laddr); ospfh->ospfh_length = htons(sizeof(struct ospfhdr) - sizeof(union ospf_types) + sizeof(struct ospf_hello_hdr)); ospf_sendmsg(&ospfsin, /* ff02::5 */ &spktinfo, /* source address, I/F */ ntohs(ospfh->ospfh_length)); if ((ife = ife->ifi_next) == ifentry) break; } taskhead->tsk_timefull.tv_sec = OSPF_T_HELLOINTERVAL; task_timer_update(taskhead); /* End of ospf_hello() */}/* * * ospf_sendmsg() * 1. fill checkksum, * 2. Actually sendmsg. * */voidospf_sendmsg(sin, pktinfo, len) struct sockaddr_in6 *sin; /* dst addr.port */ struct in6_pktinfo *pktinfo; /* src addr, outgoing I/F */ int len; /* sending data */{ int tlen; /* sizeof To addr (for Adv. API) */ int slen; /* sent data len */ struct msghdr smsghdr; /* Adv. API */ struct iovec smsgiov; /* Adv. API */ struct cmsghdr *ch; /* Adv. API */ int shoplimit; /* Adv. API */ struct ip6_pseudohdr phdr; struct ospfhdr *oh; u_int16_t cksum; static char *cmsg = NULL; /* buffer for ancillary data */ int cmsglen;#ifdef DEBUG_OSPF char in6txt[INET6_ADDRSTRLEN]; char myin6txt[INET6_ADDRSTRLEN]; char rtrid[INET_ADDRSTRLEN]; char areaid[INET_ADDRSTRLEN]; char ifname[IFNAMSIZ]; memset( in6txt, 0, INET6_ADDRSTRLEN); memset(myin6txt, 0, INET6_ADDRSTRLEN); memset( rtrid, 0, INET_ADDRSTRLEN); memset( areaid, 0, INET_ADDRSTRLEN); memset( ifname, 0, IFNAMSIZ);#endif cmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int)); if (cmsg == NULL && (cmsg = malloc(cmsglen)) == NULL) { syslog(LOG_ERR, "<%s>: malloca failed", __FUNCTION__); fatalx("malloc failed"); } memset(cmsg, 0, cmsglen); shoplimit = OSPF_HOPLIMIT;/*** Adv. API ***/ tlen = sizeof(struct sockaddr_in6); smsghdr.msg_name = (caddr_t)sin; /* dest addr.port */ smsghdr.msg_namelen = tlen; /* size of address */ smsgiov.iov_base = (void *)ospfpkt; /* buffer, base should be void */ smsgiov.iov_len = len; /* sending data len */ smsghdr.msg_iov = &smsgiov; smsghdr.msg_iovlen = 1; /* 1 iovec obj. */#ifdef ADVANCEDAPI smsghdr.msg_control = (caddr_t)cmsg; /* buffer for ancillary data */ smsghdr.msg_controllen = cmsglen;#endif smsghdr.msg_flags = 0; /* ? */ ch = CMSG_FIRSTHDR(&smsghdr);#ifdef ADVANCEDAPI ch->cmsg_level = IPPROTO_IPV6; ch->cmsg_type = IPV6_PKTINFO; ch->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); /* source address selection */ memcpy(CMSG_DATA(ch), pktinfo, sizeof(struct in6_pktinfo)); ch = CMSG_NXTHDR(&smsghdr, ch); ch->cmsg_level = IPPROTO_IPV6; ch->cmsg_type = IPV6_HOPLIMIT; /* may not be supported */ ch->cmsg_len = CMSG_LEN(sizeof(int)); memcpy(CMSG_DATA(ch), &shoplimit, sizeof(int));#else /* for hydranger */ if (IN6_IS_ADDR_MULTICAST(&sin->sin6_addr) && setsockopt(ospfsock, IPPROTO_IPV6, IPV6_MULTICAST_IF, &pktinfo->ipi6_ifindex, sizeof(u_int)) < 0) { fatal("<ospf_sendmsg>: IPV6_MULTICAST_IF"); }#endif /* ADVANCEDAPI */ memset(&phdr, 0, sizeof(phdr)); phdr.ph6_src = pktinfo->ipi6_addr; phdr.ph6_dst = sin->sin6_addr; phdr.ph6_uplen = len; phdr.ph6_nxt = IPPROTO_OSPF; oh = (struct ospfhdr *)ospfpkt; /* Before computing the checksum, the checksum field in the OSPF packet header is set to 0. [Page 56] */ oh->ospfh_cksum = 0; cksum = ip6_cksum(&phdr, ospfpkt); oh->ospfh_cksum = htons(cksum);/* syslog(LOG_ERR, "<ospf_sendmsg>: checksum =%x, if=%d", oh->ospfh_cksum, pktinfo->ipi6_ifindex);*/ if ((slen = sendmsg(ospfsock, &smsghdr, 0)) != len) { syslog(LOG_ERR, /* spoofing or misconfig ? */ "<ospf_sendmsg>: sendmsg: %s", strerror(errno)); return; }#ifdef DEBUG_OSPF syslog(LOG_DEBUG, "OSPFv3 SENT %s(%s) -> %s ", inet_ntop(AF_INET6, &pktinfo->ipi6_addr, myin6txt, INET6_ADDRSTRLEN), if_indextoname(pktinfo->ipi6_ifindex, ifname), inet_ntop(AF_INET6, &sin->sin6_addr, in6txt, INET6_ADDRSTRLEN)); syslog(LOG_DEBUG, "OSPFv3 SENT %s Len: %d", ospf_msgstr[oh->ospfh_type], len); syslog(LOG_DEBUG, "OSPFv3 SENT 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 /* End of ospf_sendmsg */}struct sockaddr_in6 fsock; /* sender's address *//* * * ospf_input() * */void ospf_input(){ int len; /* recvmsg */ int flen; /* sizeof From addr (for Adv. API) */ struct ifinfo *ife; struct ospflink *ol; struct ospfhdr *oh; /* OSPF header */ struct msghdr rmsghdr; /* Adv. API */ struct iovec rmsgiov; /* buffer for data (gather) */ static char *cmsg = NULL; /* buffer for ancillary data */ int cmsglen; struct cmsghdr *ch; /* Adv. API */ struct in6_pktinfo *rpktinfo; /* received I/F address */ struct in6_pktinfo spktinfo; /* sending source I/F */ int *rhoplimit; /* Adv. API */ struct ip6_pseudohdr phdr; u_int16_t cksum; struct rpcb *nbr; extern struct ifinfo *ifentry;#ifdef DEBUG_OSPF char in6txt[INET6_ADDRSTRLEN]; char myin6txt[INET6_ADDRSTRLEN]; char rtrid[INET_ADDRSTRLEN]; char areaid[INET_ADDRSTRLEN]; char ifname[IFNAMSIZ]; memset(in6txt, 0, INET6_ADDRSTRLEN); memset(myin6txt, 0, INET6_ADDRSTRLEN); memset( rtrid, 0, INET_ADDRSTRLEN); memset( areaid, 0, INET_ADDRSTRLEN); memset( ifname, 0, IFNAMSIZ);#endif cmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int)); memset(&fsock, 0, sizeof(struct sockaddr_in6)); /* sender's address */ memset(ospfbuf, 0, OSPF_BUFSIZ); memset(ospfpkt, 0, OSPF_MAXPKT); memset(&rmsghdr, 0, sizeof(struct msghdr)); memset(&rmsgiov, 0, sizeof(struct iovec)); if (cmsg == NULL && (cmsg = malloc(cmsglen)) == NULL) { syslog(LOG_ERR, "<%s>: malloc failed", __FUNCTION__); fatalx("malloc failed"); } memset(cmsg, 0, cmsglen); memset(&spktinfo, 0, sizeof(struct in6_pktinfo)); rpktinfo = NULL; rhoplimit = NULL;/*** Adv. API ***/ flen = sizeof(struct sockaddr_in6); rmsghdr.msg_name = (caddr_t)&fsock; /* sender's address */ rmsghdr.msg_namelen = flen; /* size of address */ rmsgiov.iov_base = (void *)ospfbuf; /* buffer, base should be void */ rmsgiov.iov_len = sizeof(ospfbuf); /* 1500 (receiving buffer len) */ rmsghdr.msg_iov = &rmsgiov; rmsghdr.msg_iovlen = 1; /* 1 iovec obj. */#ifdef ADVANCEDAPI rmsghdr.msg_control = (caddr_t)cmsg; /* buffer for ancillary data */ rmsghdr.msg_controllen = cmsglen;#else rmsghdr.msg_control = (caddr_t)0; rmsghdr.msg_controllen = 0;#endif /* ADVANCEDAPI */ rmsghdr.msg_flags = 0; /* ? */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -