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

📄 ripng.c

📁 同时支持IPv4和IPv6的BGP协议实现
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * 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 "aspath.h"#include "bgp_var.h"#include "in6.h"#include "ripng.h"#include "ripng_var.h"int                  ripsock;              /* socket for RIPng UDP      */int                  rip_use_sitelocal = 0;/* if we handle site-local addrs */byte                 ripbuf[RIPNG_BUFSIZ];byte                 rippkt[RIPNG_MAXPKT]; /* should discover path MTU  */struct ripif        *ripifs; struct sockaddr_in6  ripsin;               /* ff02::9.RIPNG_PORT        *//* * RIP message types */char *rip_msgstr[] = {  "",  "Request",  "Response"};/* *   rip_init() */void rip_init(){  struct ripif      *ripif;#ifndef ADVANCEDAPI  int hops;#endif  struct ifinfo     *ife;  struct timeval    tv;  extern struct ifinfo *ifentry;  ripifs = NULL;  /* random seed */  gettimeofday(&tv, NULL);  srandom(tv.tv_usec ^ tv.tv_sec);  ife = ifentry;  while (ife) {   /*  for each available I/F  */	  if (ife->ifi_flags & IFF_UP &&	      ife->ifi_flags & IFF_MULTICAST) /* XXX */	  {		  MALLOC(ripif, struct ripif);		  ripif->rip_ife   = ife;		  /* (1998/05/21) */		  if (IN6_IS_ADDR_UNSPECIFIED(&ife->ifi_laddr)) {			  ripif->rip_mode |= IFS_NORIPIN;			  ripif->rip_mode |= IFS_NORIPOUT;		  }		  if (ripifs) 			  insque(ripif, ripifs);		  else {			  ripif->rip_next = ripif->rip_prev = ripif;			  ripifs = ripif;		  }	  }	  if ((ife = ife->ifi_next) == ifentry)		  break;  }  /* End of rip_init() */}voidrip_sockinit(){  task              *tsk;  struct ripif      *ripif;  struct ipv6_mreq   mreq;  int on;  extern task          *taskhead;  extern fd_set         fdmask;  /* for RIPng */  if ((ripsock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)    fatal("<rip_init>: socket");  memset(&ripsin,   0, sizeof(ripsin));  /* sockaddr_in6  */  memset(&mreq,     0, sizeof(mreq));  ripsin.sin6_len      = sizeof(struct sockaddr_in6);  ripsin.sin6_family   = AF_INET6;  ripsin.sin6_port     = htons(RIPNG_PORT);  ripsin.sin6_flowinfo = 0;  /* bind must be called before filling RIPNG_DEST in ripsin */  if (bind(ripsock, (struct sockaddr *)&ripsin, sizeof(ripsin)) < 0)    fatal("<rip_init>: bind");  if (inet_pton(AF_INET6, RIPNG_DEST, (void *)&ripsin.sin6_addr) != 1)    fatal("<rip_init>: inet_pton");  mreq.ipv6mr_multiaddr = ripsin.sin6_addr;  for (ripif = ripifs; ripif; ) { /* XXX: odd loop */    if ((ripif->rip_mode & IFS_NORIPIN) != 0)      goto nextif;    mreq.ipv6mr_interface = ripif->rip_ife->ifi_ifn->if_index;    if (setsockopt(ripsock, IPPROTO_IPV6,		   IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) < 0)	    fatal("<rip_init>: setsockopt: IPV6_JOIN_GROUP");  nextif:    if ((ripif = ripif->rip_next) == ripifs)	    break;  }#ifndef ADVANCEDAPI  hops = RIPNG_HOPLIMIT;  if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,		 &hops, sizeof(int)) < 0)    fatal("<rip_init>: setsockopt IPV6_MULTICAST_HOPS");#endif /* ADVANCEDAPI */  on = 0;  if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,		 &on, sizeof(on)) < 0)    fatal("<rip_init>: setsockopt IPV6_MULTICAST_LOOP");#ifdef ADVANCEDAPI  on = 1;#ifdef IPV6_RECVPKTINFO  if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_RECVPKTINFO,		 &on, sizeof(on)) < 0)    fatal("<rip_init>: setsockopt(IPV6_RECVPKTINFO)");#else  /* old adv. API */  if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_PKTINFO,		 &on, sizeof(on)) < 0)    fatal("<rip_init>: setsockopt(IPV6_PKTINFO)");#endif   on = 1;#ifdef IPV6_RECVPKTINFO  if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_RECVPKTINFO,		 &on, sizeof(on)) < 0)    fatal("<rip_init>: setsockopt(IPV6_RECVPKTINFO)");#else  /* old adv. API */  if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_PKTINFO,		 &on, sizeof(on)) < 0)    fatal("<rip_init>: setsockopt(IPV6_PKTINFO)");#endif #endif /* ADVANCEDAPI */  FD_SET(ripsock,  &fdmask);  MALLOC(tsk, task);  if (taskhead) {    insque(tsk, taskhead);  } else {    taskhead      = tsk;    tsk->tsk_next = tsk;    tsk->tsk_prev = tsk;  }  tsk->tsk_timename         = RIP_DUMP_TIMER;  tsk->tsk_rip              = NULL;  tsk->tsk_timefull.tv_sec  = 1; /* immediately */   tsk->tsk_timefull.tv_usec = 0;  task_timer_update(tsk);}/* * rip_inport_init: initilize Adj_Ribs_Out for RIPng */voidrip_import_init(){  struct ripif      *ripif = ripifs;  extern byte           bgpyes;  extern struct ifinfo *ifentry;  extern struct rpcb   *bgb;  while (ripif) {    struct ripif  *outripif;    struct ifinfo *outife;    struct rpcb   *outbnp;    /*    Include ripif itself, for "specific request".    */    outripif = ripifs;    while(outripif) {	    struct rtproto *rtp;      	    MALLOC(rtp, struct rtproto);	    rtp->rtp_type = RTPROTO_RIP;	    rtp->rtp_rip  = outripif;		    if (ripif->rip_adj_ribs_out)		    insque(rtp, ripif->rip_adj_ribs_out);	    else {		    rtp->rtp_next =  rtp->rtp_prev = rtp;		    ripif->rip_adj_ribs_out        = rtp;	    }	    if ((outripif = outripif->rip_next) == ripifs)  /* global */		    break;    } /* while(outripif) */    outife = ifentry;      /* Don't include ife itself */    while (outife) {	    struct rtproto *rtp;	    if (ripif->rip_ife != outife) {		    MALLOC(rtp, struct rtproto);		    rtp->rtp_type = RTPROTO_IF;		    rtp->rtp_if   = outife;			    if (ripif->rip_adj_ribs_out)			    insque(rtp, ripif->rip_adj_ribs_out);		    else {			    rtp->rtp_next =  rtp->rtp_prev = rtp;			    ripif->rip_adj_ribs_out        = rtp;		    }	    }	    if ((outife = outife->ifi_next) == ifentry)  /* global */		    break;    } /* while(outife) */    if (bgpyes) {	    outbnp = bgb;	    while(outbnp) {/* Import All eBGP routes into RIP (1998/05/21) */		    struct rtproto *rtp;		    if (!(outbnp->rp_mode & BGPO_IGP)) {			    MALLOC(rtp, struct rtproto);			    rtp->rtp_type = RTPROTO_BGP;			    rtp->rtp_bgp  = outbnp;				    if (ripif->rip_adj_ribs_out)				    insque(rtp, ripif->rip_adj_ribs_out);			    else {				    rtp->rtp_next =  rtp->rtp_prev = rtp;				    ripif->rip_adj_ribs_out        = rtp;			    }		    }      		    if ((outbnp = outbnp->rp_next) == bgb)  /* global */			    break;	    } /* while (struct rpcb) */    }          if ((ripif = ripif->rip_next) == ripifs)	    break;  } /* while (global "ripifs") */ }/* *   rip_query_dump() */voidrip_query_dump(){  struct ripif        *ripif;  struct in6_pktinfo   spktinfo;  struct riphdr       *rp;  struct ripinfo6     *np;         /* RIPng RTE              */  memset(rippkt, 0, RIPNG_MAXPKT);  rp = (struct riphdr *)rippkt;    /* outgoing RIPng header  */  rp->riph_cmd   = RIPNGCMD_REQUEST;  rp->riph_vers  = RIPNG_VERSION;  rp->riph_zero2 = 0;  np  = (struct ripinfo6 *)(rippkt + sizeof(struct riphdr));  np->rip6_metric = RIPNG_METRIC_UNREACHABLE;  ripif = ripifs; /* global */  while(ripif) {    if (!(ripif->rip_mode & IFS_NORIPOUT)) {      spktinfo.ipi6_addr    = ripif->rip_ife->ifi_laddr;  /* copy */      spktinfo.ipi6_ifindex = ripif->rip_ife->ifi_ifn->if_index;      if (rip_sendmsg(&ripsin,      /* ff02::9.RIPNG_PORT  */		      &spktinfo,    /* source address, I/F */		      sizeof(struct riphdr) + sizeof(struct ripinfo6)))	ripif->rip_reqsentfail++;      ripif->rip_requestsent++;    }    if ((ripif = ripif->rip_next) == ripifs)      break;  }}struct sockaddr_in6 fsock;  /* sender's address *//* * *   rip_input() * */void rip_input(){  struct ripif       *ripif;  int                 nn;     /* number of RTEs                  */  int                 len;    /* recvmsg                         */  int                 flen;   /* sizeof From addr (for Adv. API) */  struct ifinfo      *ife;  struct riphdr      *rp;     /* RIPng header                    */  extern struct ifinfo *ifentry;  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 */  char                ifname[IFNAMSIZ];  cmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int));  memset(&fsock,    0, sizeof(struct sockaddr_in6)); /* sender's addr/port */  memset(ripbuf,    0, RIPNG_BUFSIZ);  memset(rippkt,    0, RIPNG_MAXPKT);  memset(&rmsghdr,  0, sizeof(struct msghdr));  memset(&rmsgiov,  0, sizeof(struct iovec));  if (cmsg == NULL && (cmsg = malloc(cmsglen)) == NULL) {    fatalx("<rip_input>: 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 addr/port          */  rmsghdr.msg_namelen    = flen;            /* size of address             */  rmsgiov.iov_base       = (void *)ripbuf;  /* buffer, base should be void */  rmsgiov.iov_len        = sizeof(ripbuf);  /* 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; /* ? */  len = 0;  if ((len = recvmsg(ripsock, &rmsghdr, 0)) < 0)   /* Adv. API */    fatal("<rip_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 &&	ch->cmsg_len   == CMSG_LEN(sizeof(int))) {      rhoplimit = (int *)CMSG_DATA(ch);    }  }  if (rpktinfo == NULL) {    fatalx("<rip_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("<rip_input>: find_if_by_addr");      rrpktinfo.ipi6_ifindex = ife->ifi_ifn->if_index;      rpktinfo = &rrpktinfo;  }#endif /* ADVANCEDAPI */  IFLOG(LOG_RIP)	  syslog(LOG_DEBUG, "RIPng RECV from %s+%d (%s)",		 ip6str2(&fsock), ntohs(fsock.sin6_port),		 if_indextoname(rpktinfo->ipi6_ifindex, ifname));  /* Received I/F */  if ((ripif = find_rip_by_index((u_int)rpktinfo->ipi6_ifindex)) == NULL) {    syslog(LOG_ERR,	   "<rip_input>: RIP received at Unknown I/F %d (ignored)",	   rpktinfo->ipi6_ifindex);    return;

⌨️ 快捷键说明

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