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

📄 rt_table.c

📁 同时支持IPv4和IPv6的BGP协议实现
💻 C
📖 第 1 页 / 共 3 页
字号:
 *    addroute() */intaddroute(rte, gw, ife)        struct rt_entry       *rte;        const struct in6_addr *gw;        struct ifinfo         *ife;{        struct  ripinfo6 *np;        static  u_long  seq = 0;        u_char  buf[BUFSIZ];        struct  rt_msghdr       *rtm;        struct  sockaddr_in6    *sin;        int     len, wlen;	char    in6txt[INET6_ADDRSTRLEN];	char    gw6txt[INET6_ADDRSTRLEN];	extern int rtsock;	extern pid_t pid;	if (rte == NULL || gw == NULL || ife == NULL) {	  syslog(LOG_ERR, "<%s>: invalid argument", __FUNCTION__);	  return -1;	}	memset(in6txt, 0, INET6_ADDRSTRLEN);	memset(gw6txt, 0, INET6_ADDRSTRLEN);	memset(buf,    0, BUFSIZ);	np = &rte->rt_ripinfo;        memset(buf, 0, sizeof(buf));        rtm = (struct rt_msghdr *)buf;        rtm->rtm_type = RTM_ADD;        rtm->rtm_version = RTM_VERSION;        rtm->rtm_seq = seq++;        rtm->rtm_pid = pid;        rtm->rtm_flags = rte->rt_flags & RTF_ROUTE_H;        rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_IFA;	switch (rte->rt_proto.rtp_type) {	case RTPROTO_RIP: case RTPROTO_OSPF: case RTPROTO_IF:	  rtm->rtm_rmx.rmx_hopcount = np->rip6_metric;	  break;	case RTPROTO_BGP:	  if (rte->rt_aspath == NULL)	    fatalx("NULL AS path");	  rtm->rtm_rmx.rmx_hopcount = aspath2cost(rte->rt_aspath);	  break;	default:	  fatalx("<addroute>: BUG !");	  break;	}        rtm->rtm_inits = RTV_HOPCOUNT;        sin = (struct sockaddr_in6 *)&buf[sizeof(struct rt_msghdr)];        /* Destination */        sin->sin6_len = sizeof(struct sockaddr_in6);        sin->sin6_family = AF_INET6;        sin->sin6_addr = np->rip6_dest;	sin = (struct sockaddr_in6 *)((char *)sin + ROUNDUP(sin->sin6_len));        /* Gateway */        sin->sin6_len = sizeof(struct sockaddr_in6);        sin->sin6_family = AF_INET6;        sin->sin6_addr = *gw;	if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr))	  SET_IN6_LINKLOCAL_IFINDEX(&sin->sin6_addr, ife->ifi_ifn->if_index);	sin = (struct sockaddr_in6 *)((char *)sin + ROUNDUP(sin->sin6_len));        /* Netmask */        sin->sin6_len = sizeof(struct sockaddr_in6);        sin->sin6_family = AF_INET6;        mask_nset(&sin->sin6_addr, np->rip6_plen);	sin = (struct sockaddr_in6 *)((char *)sin + ROUNDUP(sin->sin6_len));        /* Interface */        sin->sin6_len = sizeof(struct sockaddr_in6);        sin->sin6_family = AF_INET6;        sin->sin6_addr = ife->ifi_laddr;	sin = (struct sockaddr_in6 *)((char *)sin + ROUNDUP(sin->sin6_len));        len = (char *)sin - (char *)buf;        rtm->rtm_msglen = len;	errno = 0;        if ((wlen = write(rtsock, buf, len)) == len) {	  IFLOG(LOG_ROUTE)	    syslog(LOG_DEBUG, "<%s>: %s/%d gw=%s tag=%d%s, succeed",		   __FUNCTION__,		   ip6str(&np->rip6_dest, 0), np->rip6_plen,		   ip6str((struct in6_addr *)gw, 0), ntohs(np->rip6_tag),		   rte->rt_flags & RTF_IGP_EGP_SYNC ? "(sync)":"");	  aggr_ckconf(rte);	  return 0;	} else {	  int errorlevel;	  if (errno == EEXIST) {  /* doubtful "File exists" */	    aggr_ckconf(rte);	    return 0;	  }	  /*	   * If the specified next hop is not a link-local address	   * and it is an IBGP route, it may have been specified in a	   * next hop field of a BGP4+. In IBGP cases, it is usually a off-link	   * gateway, so adding the route is tend to fail.	   */	  if (rte->rt_proto.rtp_type == RTPROTO_BGP &&	      rte->rt_proto.rtp_bgp->rp_mode & BGPO_IGP &&	      !IN6_IS_ADDR_LINKLOCAL(gw))		  errorlevel = LOG_DEBUG; /* use a lower log level */	  else		  errorlevel = LOG_ERR;	  syslog(errorlevel,		 "<%s>: %s/%d gw=%s, failed: %s",		 __FUNCTION__,		 inet_ntop(AF_INET6, &np->rip6_dest, in6txt, INET6_ADDRSTRLEN),		 np->rip6_plen,		 inet_ntop(AF_INET6, gw,             gw6txt, INET6_ADDRSTRLEN),		 strerror(errno));	  return -1;	}}/* *    delroute() */#define AGGR_DECLEM(rte) { if (rte->rt_aggr.ag_agg) \			     rte->rt_aggr.ag_agg->rt_aggr.ag_refcnt -- ; }intdelroute(rte, gw)        struct rt_entry *rte;        struct in6_addr *gw;{        struct ripinfo6 *rp;        static  u_long  seq = 0;        u_char  buf[BUFSIZ];        struct  rt_msghdr       *rtm;        struct  sockaddr_in6    *sin;        int     len;	char    in6txt[INET6_ADDRSTRLEN];	char    gw6txt[INET6_ADDRSTRLEN];	extern int rtsock;	extern pid_t pid;	if (rte == NULL) {	  syslog(LOG_ERR, "<%s>: invalid argument", __FUNCTION__);	  return -1;	}	memset(buf,    0, BUFSIZ);	memset(in6txt, 0, INET6_ADDRSTRLEN);	memset(gw6txt, 0, INET6_ADDRSTRLEN);	rp = &rte->rt_ripinfo;        bzero(buf, sizeof(buf));        rtm = (struct rt_msghdr *)buf;        rtm->rtm_type = RTM_DELETE;        rtm->rtm_version = RTM_VERSION;        rtm->rtm_seq = seq++;        rtm->rtm_pid = pid;	rtm->rtm_flags  = rte->rt_flags & RTF_ROUTE_H;        rtm->rtm_flags |= RTF_UP | RTF_GATEWAY;/*       rtm->rtm_flags = RTF_UP | RTF_GATEWAY; */        rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;        sin = (struct sockaddr_in6 *)&buf[sizeof(struct rt_msghdr)];        /* Destination */        sin->sin6_len = sizeof(struct sockaddr_in6);        sin->sin6_family = AF_INET6;        sin->sin6_addr = rp->rip6_dest;	sin = (struct sockaddr_in6 *)((char *)sin + ROUNDUP(sin->sin6_len));        /* Gateway */	if (gw) {	  sin->sin6_len = sizeof(struct sockaddr_in6);	  sin->sin6_family = AF_INET6;	  sin->sin6_addr = *gw;	  sin = (struct sockaddr_in6 *)((char *)sin + ROUNDUP(sin->sin6_len));	}        /* Netmask */        sin->sin6_len = sizeof(struct sockaddr_in6);        sin->sin6_family = AF_INET6;        mask_nset(&sin->sin6_addr, rp->rip6_plen);	sin = (struct sockaddr_in6 *)((char *)sin + ROUNDUP(sin->sin6_len));        len = (char *)sin - (char *)buf;        rtm->rtm_msglen = len;	errno = 0;        if (write(rtsock, buf, len) == len) {	  IFLOG(LOG_ROUTE)	    syslog(LOG_DEBUG, "<%s>: %s/%d gw=%s tag=%d%s, succeed",		   __FUNCTION__,		   ip6str(&rp->rip6_dest, 0), rp->rip6_plen,		   gw ? ip6str(gw, 0) : "NULL",		   ntohs(rp->rip6_tag),		   rte->rt_flags & RTF_IGP_EGP_SYNC ? "(sync)":"");	  AGGR_DECLEM(rte);	  return 0;	} else {	  if (errno == ESRCH) {  /* doubtful "No such process" */	    AGGR_DECLEM(rte);	    return 0;	  }	  syslog(LOG_ERR,		 "<%s>: %s/%d gw=%s, failed: %s",		 __FUNCTION__,		 inet_ntop(AF_INET6, &rp->rip6_dest, in6txt, INET6_ADDRSTRLEN),		 rp->rip6_plen,		 gw ? inet_ntop(AF_INET6, gw, gw6txt, INET6_ADDRSTRLEN) :		 "NULL", strerror(errno));	  return -1;	}}/* *   chroute() *      Change metric. */intchroute(rte, gw, ife)        struct rt_entry       *rte;        const struct in6_addr *gw;        struct ifinfo *ife;{        struct  ripinfo6 *np;        static  u_long  seq = 0;        u_char  buf[BUFSIZ];        struct  rt_msghdr       *rtm;        struct  sockaddr_in6    *sin;        int     len, wlen;	char    in6txt[INET6_ADDRSTRLEN];	char    gw6txt[INET6_ADDRSTRLEN];	extern int rtsock;	extern pid_t pid;	if (rte == NULL || gw == NULL || ife == NULL) {	  syslog(LOG_ERR, "<chroute>: invalid argument");	  return -1;	}	memset(in6txt, 0, INET6_ADDRSTRLEN);	memset(gw6txt, 0, INET6_ADDRSTRLEN);	memset(buf,    0, BUFSIZ);	np = &rte->rt_ripinfo;        memset(buf, 0, sizeof(buf));        rtm = (struct rt_msghdr *)buf;        rtm->rtm_type = RTM_CHANGE;        rtm->rtm_version = RTM_VERSION;        rtm->rtm_seq = seq++;        rtm->rtm_pid = pid;        rtm->rtm_flags = rte->rt_flags & RTF_ROUTE_H;        rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_IFA;	switch (rte->rt_proto.rtp_type) {	case RTPROTO_RIP:	  rtm->rtm_rmx.rmx_hopcount = np->rip6_metric;	  break;	case RTPROTO_BGP:	  if (rte->rt_aspath == NULL)	    fatalx("<chroute>: BUG !");	  rtm->rtm_rmx.rmx_hopcount = aspath2cost(rte->rt_aspath);	  break;	default:	  fatalx("<chroute>: BUG !");	  break;	}        rtm->rtm_inits = RTV_HOPCOUNT;        sin = (struct sockaddr_in6 *)&buf[sizeof(struct rt_msghdr)];        /* Destination */        sin->sin6_len = sizeof(struct sockaddr_in6);        sin->sin6_family = AF_INET6;        sin->sin6_addr = np->rip6_dest;	sin = (struct sockaddr_in6 *)((char *)sin + ROUNDUP(sin->sin6_len));        /* Gateway */        sin->sin6_len = sizeof(struct sockaddr_in6);        sin->sin6_family = AF_INET6;        sin->sin6_addr = *gw;	if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr))	  SET_IN6_LINKLOCAL_IFINDEX(&sin->sin6_addr, ife->ifi_ifn->if_index);	sin = (struct sockaddr_in6 *)((char *)sin + ROUNDUP(sin->sin6_len));        /* Netmask */        sin->sin6_len = sizeof(struct sockaddr_in6);        sin->sin6_family = AF_INET6;        mask_nset(&sin->sin6_addr, np->rip6_plen);	sin = (struct sockaddr_in6 *)((char *)sin + ROUNDUP(sin->sin6_len));        /* Interface */        sin->sin6_len = sizeof(struct sockaddr_in6);        sin->sin6_family = AF_INET6;        sin->sin6_addr = ife->ifi_laddr;	sin = (struct sockaddr_in6 *)((char *)sin + ROUNDUP(sin->sin6_len));        len = (char *)sin - (char *)buf;        rtm->rtm_msglen = len;        if ((wlen = write(rtsock, buf, len)) == len) {	  IFLOG(LOG_ROUTE)	    syslog(LOG_DEBUG, "<%s>: %s/%d gw=%s met=%lu, succeed",		   __FUNCTION__,		   ip6str(&np->rip6_dest, 0), np->rip6_plen,		   ip6str((struct in6_addr *)gw, 0),		   (u_long)rtm->rtm_rmx.rmx_hopcount);	} else {	  syslog(LOG_ERR,		 "<chroute>: %s/%d gw=%s met=%lu, failed: %s",		 inet_ntop(AF_INET6, &np->rip6_dest, in6txt, INET6_ADDRSTRLEN),		 np->rip6_plen,		 inet_ntop(AF_INET6, gw,             gw6txt, INET6_ADDRSTRLEN),		 (u_long)rtm->rtm_rmx.rmx_hopcount,		 strerror(errno));	  return -1;	}        return 0;  /*  End of chroute() */}/* *  igp_enable_rte() *     DESCRIPTION:  Kernel addroute(). *                   Insert a rte into ripif|rpcb adj_ribs_in. *                   NextHop must be specified. * *     RETURN VALUES:  copy of rte. */struct rt_entry *igp_enable_rte(rte)     struct rt_entry *rte;{  struct ifinfo   *ife = NULL;  struct rt_entry **adj_ribs_in = NULL;  struct rt_entry *crte;  /* copied */  switch(rte->rt_proto.rtp_type) {  case RTPROTO_RIP:    ife         = rte->rt_proto.rtp_rip->rip_ife;    adj_ribs_in = &(rte->rt_proto.rtp_rip->rip_adj_ribs_in);    break;  case RTPROTO_OSPF:    ife         = rte->rt_proto.rtp_ospf->rp_ife;    adj_ribs_in = &(rte->rt_proto.rtp_ospf->rp_adj_ribs_in);    break;  default:    fatalx("<igp_enable_rte>: Bad routing protocol");    /* NOTRECHED */  }  if (rte->rt_flags & RTF_UP)    if (addroute(rte, &rte->rt_gw, ife) != 0) {      syslog(LOG_ERR, "%s: route couldn't be added.", __FUNCTION__);      return NULL;    }  /* check if some BGP routes can be enabled by this route */  bgp_enable_rte_by_igp(rte);  if (*adj_ribs_in)    insque(rte, *adj_ribs_in);  else {    rte->rt_next = rte->rt_prev = rte;    *adj_ribs_in = rte;  }  MALLOC(crte, struct rt_entry);  memcpy(crte, rte, sizeof(struct rt_entry));  return crte;}/* *  rte_remove() *     Remove and Free ONE.  Exact match. *       If Solo entry, Frees ASpath, too. */struct rt_entry *rte_remove(key, base)     struct rt_entry *key;     struct rt_entry *base;{  struct rt_entry *rte;  if (key == NULL)    return base;  if ((rte = base) == NULL)    return NULL;  while(rte) {    if (rte->rt_proto.rtp_type > RTPROTO_MAX)    /* safety check */      fatalx("<rte_remove>: rt_proto.rtp_type corrupt");    if (key == rte) {	    IFLOG(LOG_ROUTE)		    syslog(LOG_DEBUG,			   "<%s>: %s/%d gw=%s, removed", __FUNCTION__,			   ip6str(&rte->rt_ripinfo.rip6_dest, 0),			   rte->rt_ripinfo.rip6_plen,			   ip6str(&rte->rt_gw, 0));	    free_aspath(rte->rt_aspath); /* argument validation will be in free_aspath */	    if (rte == base) {		    /* RTE is the first entry of the list. Treat it carefully */

⌨️ 快捷键说明

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