📄 rt_table.c
字号:
* 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 + -