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

📄 ospf.c

📁 同时支持IPv4和IPv6的BGP协议实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 + -