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

📄 rt_table.c

📁 同时支持IPv4和IPv6的BGP协议实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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 "aspath.h"#include "rt_table.h"#include "bgp_var.h"#include "in6.h"#include "ripng.h"struct rt_entry static_rte_head = {&static_rte_head, &static_rte_head};/* alignment constraint for routing socket messages */#define ROUNDUP(a) \	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))voidkrt_init(){  int    mib[6];  size_t msize;  char *buf, *p, *lim;  struct rt_msghdr *rtm;  extern int rtsock;  mib[0] = CTL_NET;  mib[1] = PF_ROUTE;  mib[2] = 0;  mib[3] = AF_INET6;      /* Address family */  mib[4] = NET_RT_DUMP;   /* Dump the kernel routing table */  mib[5] = 0;             /* No flags */  if (sysctl(mib, 6, NULL, &msize, NULL, 0) < 0)    fatal("<krt_init>: sysctl estimate");  if ((buf = (char *)malloc(msize)) == NULL)    fatalx("<krt_init>: malloc");  if (sysctl(mib, 6, buf, &msize, NULL, 0) < 0)    fatal("<krt_init>: sysctl NET_RT_DUMP");  if ((rtsock = socket(PF_ROUTE, SOCK_RAW, AF_INET6)) < 0)    fatal("<krt_init>: routing socket");  /* force Routing socket write-only */  if (shutdown(rtsock, 0) < 0)    fatal("<krt_init>: shutdown");  lim = buf + msize;  for (p = buf; p < lim; p += rtm->rtm_msglen) {    rtm = (struct rt_msghdr *)p;    krt_entry(rtm);  }  free(buf);}/* *   krt_entry() *      Flush dinamic-network-routes.  *      Construct the initial "rt_entry" list. */voidkrt_entry(rtm)     struct rt_msghdr *rtm;{  struct  sockaddr_in6 *sin6_dst, *sin6_gw, *sin6_mask;  struct  sockaddr_in6 *sin6_genmask, *sin6_ifp;  char   *rtmp, *ifname;  char    buf[BUFSIZ];  struct  rt_entry *rrt;  struct  ripinfo6 *np;  struct  ifinfo   *ife;  int               s;  extern  int       rtsock;  /*  Interface  */  if ((s = rtm->rtm_index))    ifname = if_indextoname(s, buf);    else       fatalx("<krt_entry>: Unkown interface");  sin6_dst = sin6_gw = sin6_mask = sin6_genmask = sin6_ifp = 0;  if ((rtm->rtm_flags & RTF_UP) == 0 ||#ifdef __FreeBSD__      (rtm->rtm_flags & (RTF_XRESOLVE|RTF_WASCLONED))#endif /* __FreeBSD__ */#ifdef __bsdi__      (rtm->rtm_flags & (RTF_XRESOLVE|RTF_CLONED))#endif /*__bsdi__*/#if defined(__NetBSD__) || defined(__OpenBSD__)      (rtm->rtm_flags & (RTF_XRESOLVE))#endif /* __NetBSD__ || __OpenBSD__ */      )    return;             /* not interested in the link route */  rtmp = (char *)(rtm + 1);  /* Destination */  if ((rtm->rtm_addrs & RTA_DST) == 0) /* ignore routes without destination */    return;                            /*                           address */  sin6_dst = (struct sockaddr_in6 *)rtmp;  if (!IN6_IS_ADDR_ROUTABLE(&sin6_dst->sin6_addr))    return;  rtmp += sin6_dst->sin6_len;               /* char pointer */  if (rtm->rtm_addrs & RTA_GATEWAY) {    sin6_gw = (struct sockaddr_in6 *)rtmp;    rtmp += ROUNDUP(sin6_gw->sin6_len);  }  if (rtm->rtm_addrs & RTA_NETMASK) {    sin6_mask = (struct sockaddr_in6 *)rtmp;    rtmp += ROUNDUP(sin6_mask->sin6_len);  }  if (rtm->rtm_addrs & RTA_GENMASK) {    sin6_genmask = (struct sockaddr_in6 *)rtmp;    rtmp += ROUNDUP(sin6_genmask->sin6_len);  }  if (rtm->rtm_addrs & RTA_IFP) {    sin6_ifp = (struct sockaddr_in6 *)rtmp;    rtmp += ROUNDUP(sin6_ifp->sin6_len);  }#if 0  /* checking previously added P-to-P self route (1998/04/24) */  if (IN6_IS_ADDR_LOOPBACK(&sin6_gw->sin6_addr))    return;#endif  /* flush */  if (!(rtm->rtm_flags & RTF_STATIC)  &&       (rtm->rtm_flags & RTF_GATEWAY)) {    int len;    rtm->rtm_type = RTM_DELETE;    rtm->rtm_seq  = 0;          /*  ???  */    len = write(rtsock, (char *)rtm, rtm->rtm_msglen);    if (len < (int)rtm->rtm_msglen) {      fatalx("<krt_entry>: write failed routing socket");    }    return;  }  MALLOC(rrt, struct rt_entry);  /* a new space */  np = &rrt->rt_ripinfo;  rrt->rt_aspath  = NULL;        /* because I/F direct RTE */  rrt->rt_riptime = NULL;  np->rip6_metric = rtm->rtm_rmx.rmx_hopcount;  /* direct RTE metric = 0 */  rrt->rt_flags = rtm->rtm_flags;  np->rip6_dest = sin6_dst->sin6_addr;  /* Prefix length (from routing socket) */  if (rtm->rtm_flags & RTF_HOST)                  /* host route */    np->rip6_plen = 128;  else if (sin6_mask)                             /*   other    */    np->rip6_plen = mask2len(sin6_mask);  else    np->rip6_plen = 0;  /* Gateway (i.e. next hop) */  if (sin6_gw == NULL)    memset(&rrt->rt_gw, 0, sizeof(struct in6_addr));  else    rrt->rt_gw = sin6_gw->sin6_addr;  /* Check gateway */  if (!IN6_IS_ADDR_LINKLOCAL(&rrt->rt_gw)) {    rrt->rt_flags |= RTF_NH_NOT_LLADDR;  }  if ((ife = find_if_by_index(s)) == NULL)    fatalx("<krt_entry>: I/F not found");  if (find_rte(rrt, ife->ifi_rte)) {    /* Already found ? */    free(rrt);    return;  }  rrt->rt_proto.rtp_type = RTPROTO_IF;  rrt->rt_proto.rtp_if   = ife;  /* Put "rrt" into the I/F's RTE-list */  if (ife->ifi_rte != NULL) {    insque(rrt, ife->ifi_rte);  } else {    rrt->rt_next = rrt;    rrt->rt_prev = rrt;    ife->ifi_rte = rrt;  };#if 0 /* KAME kernel automatically install such routes */  /*   * Add a route for our own address on a point-to-point interface.   */  if ((sin6_gw->sin6_family == AF_INET6) &&      IN6_IS_ADDR_ROUTABLE(&sin6_gw->sin6_addr) &&      ife->ifi_flags & IFF_POINTOPOINT) {    struct rt_entry *rte;    MALLOC(rte, struct rt_entry);  /* a new space */    np = &rte->rt_ripinfo;    np->rip6_dest   = sin6_gw->sin6_addr;    /* in6_addr              */    np->rip6_plen   = 128;    np->rip6_metric = 0;                     /* direct RTE metric = 0 */    rte->rt_gw      = in6addr_loopback;    rte->rt_flags = RTF_UP|RTF_GATEWAY|RTF_HOST;  /* UGH */    rte->rt_proto.rtp_type = RTPROTO_IF;    rte->rt_proto.rtp_if   = ife;    addroute(rte, &rte->rt_gw, ife);    /* Put "rte" into the I/F's RTE-list */    insque(rte, ife->ifi_rte);    return;  }#endif  /*  End of krt_entry()  */}/* *    find_rte() */struct rt_entry *find_rte(key, base)     struct rt_entry *key;     struct rt_entry *base;{  struct rt_entry *rte;  if ((key == NULL) ||      ((rte = base) == NULL))    return NULL;  while(rte) {    if (key->rt_ripinfo.rip6_plen == rte->rt_ripinfo.rip6_plen &&	IN6_ARE_PRFX_EQUAL(&rte->rt_ripinfo.rip6_dest,			   &key->rt_ripinfo.rip6_dest,			   key->rt_ripinfo.rip6_plen))      break;    if ((rte = rte->rt_next) == base)      return NULL;    if (rte == rte->rt_next)      fatalx("<find_rte>: BUG");  }  return rte;}intset_nexthop(dst, ret_rte)     struct in6_addr *dst;     struct rt_entry *ret_rte;{  struct ifinfo   *ife, *bestife = NULL;  struct rt_entry *rte, *bestrte = NULL;  struct ripif    *ripif;  extern byte           ripyes;  extern struct ifinfo *ifentry;  extern struct ripif  *ripifs;  /* flush old nexthop */  memset(&ret_rte->rt_gw, 0, sizeof(struct in6_addr));  ret_rte->rt_gwif = NULL;  ret_rte->rt_gwsrc_type = RTPROTO_NONE;  ret_rte->rt_gwsrc_entry = NULL;  ife = ifentry; /* global */  while(ife) {    rte = ife->ifi_rte;    while(rte) {      if (IN6_ARE_PRFX_EQUAL(dst,			     &rte->rt_ripinfo.rip6_dest,			     rte->rt_ripinfo.rip6_plen)  &&	  (rte->rt_flags & RTF_UP)) {	if (bestrte == NULL ||	    bestrte->rt_ripinfo.rip6_plen < rte->rt_ripinfo.rip6_plen) {	  /* keep the route if its the 1st one or has a longer prefix */	  bestrte = rte;	  bestife = ife;	}      }      if ((rte = rte->rt_next) == ife->ifi_rte)	break;    }    if ((ife = ife->ifi_next) == ifentry)      break;  }  if (ripyes) {    ripif = ripifs; /* global */    while(ripif) {      rte = ripif->rip_adj_ribs_in;      while(rte) {	if (IN6_ARE_PRFX_EQUAL(dst,			       &rte->rt_ripinfo.rip6_dest,			       rte->rt_ripinfo.rip6_plen)  &&	    (rte->rt_flags & RTF_UP) &&	    rte->rt_ripinfo.rip6_metric != RIPNG_METRIC_UNREACHABLE) {	  if (bestrte == NULL ||	      bestrte->rt_ripinfo.rip6_plen < rte->rt_ripinfo.rip6_plen) {	    /* keep the route if its the 1st one or has a longer prefix */	    bestrte = rte;	    bestife = ripif->rip_ife;	  }	}	if ((rte = rte->rt_next) == ripif->rip_adj_ribs_in)	  break;      }      if ((ripif = ripif->rip_next) == ripifs)	break;    }  }  if (bestrte) {    ret_rte->rt_gwif = bestife;    ret_rte->rt_gwsrc_type = bestrte->rt_proto.rtp_type;    ret_rte->rt_gwsrc_entry = bestrte;    switch(bestrte->rt_proto.rtp_type) {    case RTPROTO_IF:      /*       * If the destination resides in a local network, just use the       * destination as gateway.       * XXX: this might cause non-link-local gateway to be installed       *      in the kernel. Should we look up the neighbor cache??       */      memcpy(&ret_rte->rt_gw, dst, sizeof(struct in6_addr));      break;    case RTPROTO_RIP:      memcpy(&ret_rte->rt_gw, &bestrte->rt_gw, sizeof(struct in6_addr));      break;    default:      fatalx("<set_nexthop>: BUG(bogus gwsrc protocol");      /* NOTREACHED */    }    return 1;			/* success */  }  return 0;  /* not found */}/* * find_filter() * RETURN VALUES:  1: found *                 0: not found */intfind_filter(head, filter)	struct filtinfo *head, *filter;{	struct filtinfo *search = head;	while (search) {		if (IN6_ARE_ADDR_EQUAL(&head->filtinfo_addr,				       &filter->filtinfo_addr) &&		    head->filtinfo_plen == filter->filtinfo_plen)			return(1);		if ((search = search->filtinfo_next) == head)			break;	}	return(0);}/*

⌨️ 快捷键说明

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