?? ripngd.c
字號:
apply_mask_ipv6. */ apply_mask_ipv6 (&p); /* Apply input filters. */ ri = ifp->info; if (ri->list[RIPNG_FILTER_IN]) { if (access_list_apply (ri->list[RIPNG_FILTER_IN], &p) == FILTER_DENY) { if (IS_RIPNG_DEBUG_PACKET) zlog_info ("RIPng %s/%d is filtered by distribute in", inet6_ntop (&p.prefix), p.prefixlen); return; } } if (ri->prefix[RIPNG_FILTER_IN]) { if (prefix_list_apply (ri->prefix[RIPNG_FILTER_IN], &p) == PREFIX_DENY) { if (IS_RIPNG_DEBUG_PACKET) zlog_info ("RIPng %s/%d is filtered by prefix-list in", inet6_ntop (&p.prefix), p.prefixlen); return; } } /* Modify entry. */ if (ri->routemap[RIPNG_FILTER_IN]) { int ret; struct ripng_info newinfo; memset (&newinfo, 0, sizeof (struct ripng_info)); newinfo.metric = rte->metric; ret = route_map_apply (ri->routemap[RIPNG_FILTER_IN], (struct prefix *)&p, RMAP_RIPNG, &newinfo); if (ret == RMAP_DENYMATCH) { if (IS_RIPNG_DEBUG_PACKET) zlog_info ("RIPng %s/%d is filtered by route-map in", inet6_ntop (&p.prefix), p.prefixlen); return; } rte->metric = newinfo.metric; } /* Set nexthop pointer. */ if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) nexthop = &ripng_nexthop->address; else nexthop = &from->sin6_addr; /* Lookup RIPng routing table. */ rp = route_node_get (ripng->table, (struct prefix *) &p); if (rp->info == NULL) { /* Now, check to see whether there is already an explicit route for the destination prefix. If there is no such route, add this route to the routing table, unless the metric is infinity (there is no point in adding a route which unusable). */ if (rte->metric != RIPNG_METRIC_INFINITY) { rinfo = ripng_info_new (); /* - Setting the destination prefix and length to those in the RTE. */ rp->info = rinfo; rinfo->rp = rp; /* - Setting the metric to the newly calculated metric (as described above). */ rinfo->metric = rte->metric; rinfo->tag = ntohs (rte->tag); /* - Set the next hop address to be the address of the router from which the datagram came or the next hop address specified by a next hop RTE. */ IPV6_ADDR_COPY (&rinfo->nexthop, nexthop); IPV6_ADDR_COPY (&rinfo->from, &from->sin6_addr); rinfo->ifindex = ifp->ifindex; /* - Initialize the timeout for the route. If the garbage-collection timer is running for this route, stop it. */ ripng_timeout_update (rinfo); /* - Set the route change flag. */ rinfo->flags |= RIPNG_RTF_CHANGED; /* - Signal the output process to trigger an update (see section 2.5). */ ripng_event (RIPNG_TRIGGERED_UPDATE, 0); /* Finally, route goes into the kernel. */ rinfo->type = ZEBRA_ROUTE_RIPNG; rinfo->sub_type = RIPNG_ROUTE_RTE; ripng_zebra_ipv6_add (&p, &rinfo->nexthop, rinfo->ifindex); rinfo->flags |= RIPNG_RTF_FIB; /* Aggregate check. */ ripng_aggregate_increment (rp, rinfo); } } else { rinfo = rp->info; /* If there is an existing route, compare the next hop address to the address of the router from which the datagram came. If this datagram is from the same router as the existing route, reinitialize the timeout. */ same = (IN6_ARE_ADDR_EQUAL (&rinfo->from, &from->sin6_addr) && (rinfo->ifindex == ifp->ifindex)); if (same) ripng_timeout_update (rinfo); /* Next, compare the metrics. If the datagram is from the same router as the existing route, and the new metric is different than the old one; or, if the new metric is lower than the old one; do the following actions: */ if ((same && rinfo->metric != rte->metric) || rte->metric < rinfo->metric) { /* - Adopt the route from the datagram. That is, put the new metric in, and adjust the next hop address (if necessary). */ oldmetric = rinfo->metric; rinfo->metric = rte->metric; rinfo->tag = ntohs (rte->tag); if (! IN6_ARE_ADDR_EQUAL (&rinfo->nexthop, nexthop)) { ripng_zebra_ipv6_delete (&p, &rinfo->nexthop, rinfo->ifindex); ripng_zebra_ipv6_add (&p, nexthop, ifp->ifindex); rinfo->flags |= RIPNG_RTF_FIB; IPV6_ADDR_COPY (&rinfo->nexthop, nexthop); } IPV6_ADDR_COPY (&rinfo->from, &from->sin6_addr); rinfo->ifindex = ifp->ifindex; /* - Set the route change flag and signal the output process to trigger an update. */ rinfo->flags |= RIPNG_RTF_CHANGED; ripng_event (RIPNG_TRIGGERED_UPDATE, 0); /* - If the new metric is infinity, start the deletion process (described above); */ if (rinfo->metric == RIPNG_METRIC_INFINITY) { /* If the new metric is infinity, the deletion process begins for the route, which is no longer used for routing packets. Note that the deletion process is started only when the metric is first set to infinity. If the metric was already infinity, then a new deletion process is not started. */ if (oldmetric != RIPNG_METRIC_INFINITY) { /* - The garbage-collection timer is set for 120 seconds. */ RIPNG_TIMER_ON (rinfo->t_garbage_collect, ripng_garbage_collect, ripng->garbage_time); RIPNG_TIMER_OFF (rinfo->t_timeout); /* - The metric for the route is set to 16 (infinity). This causes the route to be removed from service.*/ /* - The route change flag is to indicate that this entry has been changed. */ /* - The output process is signalled to trigger a response. */ ; /* Above processes are already done previously. */ } } else { /* otherwise, re-initialize the timeout. */ ripng_timeout_update (rinfo); /* Should a new route to this network be established while the garbage-collection timer is running, the new route will replace the one that is about to be deleted. In this case the garbage-collection timer must be cleared. */ RIPNG_TIMER_OFF (rinfo->t_garbage_collect); } } /* Unlock tempolary lock of the route. */ route_unlock_node (rp); }}/* Add redistributed route to RIPng table. */voidripng_redistribute_add (int type, int sub_type, struct prefix_ipv6 *p, unsigned int ifindex){ struct route_node *rp; struct ripng_info *rinfo; /* Redistribute route */ if (IN6_IS_ADDR_LINKLOCAL (&p->prefix)) return; if (IN6_IS_ADDR_LOOPBACK (&p->prefix)) return; rp = route_node_get (ripng->table, (struct prefix *) p); rinfo = rp->info; if (rinfo) { RIPNG_TIMER_OFF (rinfo->t_timeout); RIPNG_TIMER_OFF (rinfo->t_garbage_collect); route_unlock_node (rp); } else { rinfo = ripng_info_new (); ripng_aggregate_increment (rp, rinfo); } rinfo->type = type; rinfo->sub_type = sub_type; rinfo->ifindex = ifindex; rinfo->metric = 1; rinfo->flags |= RIPNG_RTF_FIB; rinfo->rp = rp; rp->info = rinfo;}/* Delete redistributed route to RIPng table. */voidripng_redistribute_delete (int type, int sub_type, struct prefix_ipv6 *p, unsigned int ifindex){ struct route_node *rp; struct ripng_info *rinfo; if (IN6_IS_ADDR_LINKLOCAL (&p->prefix)) return; if (IN6_IS_ADDR_LOOPBACK (&p->prefix)) return; rp = route_node_lookup (ripng->table, (struct prefix *) p); if (rp) { rinfo = rp->info; if (rinfo != NULL && rinfo->type == type && rinfo->sub_type == sub_type && rinfo->ifindex == ifindex) { rp->info = NULL; RIPNG_TIMER_OFF (rinfo->t_timeout); RIPNG_TIMER_OFF (rinfo->t_garbage_collect); ripng_info_free (rinfo); route_unlock_node (rp); } /* For unlock route_node_lookup (). */ route_unlock_node (rp); }}/* Withdraw redistributed route. */voidripng_redistribute_withdraw (int type){ struct route_node *rp; struct ripng_info *rinfo; for (rp = route_top (ripng->table); rp; rp = route_next (rp)) if ((rinfo = rp->info) != NULL) { if (rinfo->type == type) { rp->info = NULL; RIPNG_TIMER_OFF (rinfo->t_timeout); RIPNG_TIMER_OFF (rinfo->t_garbage_collect); ripng_info_free (rinfo); route_unlock_node (rp); } }}/* RIP routing information. */voidripng_response_process (struct ripng_packet *packet, int size, struct sockaddr_in6 *from, struct interface *ifp, int hoplimit){ caddr_t lim; struct rte *rte; struct ripng_nexthop nexthop; /* RFC2080 2.4.2 Response Messages: The Response must be ignored if it is not from the RIPng port. */ if (ntohs (from->sin6_port) != RIPNG_PORT_DEFAULT) { zlog_warn ("RIPng packet comes from non RIPng port %d from %s", ntohs (from->sin6_port), inet6_ntop (&from->sin6_addr)); return; } /* The datagram's IPv6 source address should be checked to see whether the datagram is from a valid neighbor; the source of the datagram must be a link-local address. */ if (! IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr)) { zlog_warn ("RIPng packet comes from non link local address %s", inet6_ntop (&from->sin6_addr)); return; } /* It is also worth checking to see whether the response is from one of the router's own addresses. Interfaces on broadcast networks may receive copies of their own multicasts immediately. If a router processes its own output as new input, confusion is likely, and such datagrams must be ignored. */ if (ripng_lladdr_check (ifp, &from->sin6_addr)) { zlog_warn ("RIPng packet comes from my own link local address %s", inet6_ntop (&from->sin6_addr)); return; } /* As an additional check, periodic advertisements must have their hop counts set to 255, and inbound, multicast packets sent from the RIPng port (i.e. periodic advertisement or triggered update packets) must be examined to ensure that the hop count is 255. */ if (hoplimit >= 0 && hoplimit != 255) { zlog_warn ("RIPng packet comes with non 255 hop count %d from %s", hoplimit, inet6_ntop (&from->sin6_addr)); return; } /* Reset nexthop. */ memset (&nexthop, 0, sizeof (struct ripng_nexthop)); nexthop.flag = RIPNG_NEXTHOP_UNSPEC; /* Set RTE pointer. */ rte = packet->rte; for (lim = ((caddr_t) packet) + size; (caddr_t) rte < lim; rte++) { /* First of all, we have to check this RTE is next hop RTE or not. Next hop RTE is completely different with normal RTE so we need special treatment. */ if (rte->metric == RIPNG_METRIC_NEXTHOP) { ripng_nexthop_rte (rte, from, &nexthop); continue; } /* RTE information validation. */ /* - is the destination prefix valid (e.g., not a multicast prefix and not a link-local address) A link-local address should never be present in an RTE. */ if (IN6_IS_ADDR_MULTICAST (&rte->addr)) { zlog_warn ("Destination prefix is a multicast address %s/%d [%d]", inet6_ntop (&rte->addr), rte->prefixlen, rte->metric); continue; } if (IN6_IS_ADDR_LINKLOCAL (&rte->addr)) { zlog_warn ("Destination prefix is a link-local address %s/%d [%d]", inet6_ntop (&rte->addr), rte->prefixlen, rte->metric); continue; } if (IN6_IS_ADDR_LOOPBACK (&rte->addr)) { zlog_warn ("Destination prefix is a loopback address %s/%d [%d]", inet6_ntop (&rte->addr), rte->prefixlen, rte->metric); continue; } /* - is the prefix length valid (i.e., between 0 and 128, inclusive) */ if (rte->prefixlen > 128) { zlog_warn ("Invalid prefix length %s/%d from %s%%%s", inet6_ntop (&rte->addr), rte->prefixlen, inet6_ntop (&from->sin6_addr), ifp->name); continue; } /* - is the metric valid (i.e., between 1 and 16, inclusive) */ if (! (rte->metric >= 1 && rte->metric <= 16)) { zlog_warn ("Invalid metric %d from %s%%%s", rte->metric, inet6_ntop (&from->sin6_addr), ifp->name); continue; } /* Metric calculation. */ rte->metric += ifp->metric; if (rte->metric > RIPNG_METRIC_INFINITY) rte->metric = RIPNG_METRIC_INFINITY; /* Routing table updates. */ ripng_route_process (rte, from, &nexthop, ifp); }}/* Response to request message. */voidripng_request_process (struct ripng_packet *packet,int size, struct sockaddr_in6 *from, struct interface *ifp){ caddr_t lim; struct rte *rte; struct prefix_ipv6 p; struct route_node *rp; struct ripng_info *rinfo; struct ripng_interface *ri; /* Check RIPng process is enabled on this interface. */ ri = ifp->info; if (! ri->running) return; /* When passive interface is specified, suppress responses */ if (ri->passive) return; lim = ((caddr_t) packet) + size; rte = packet->rte; /* The Request is processed entry by entry. If there are no entries, no response is given. */ if (lim == (caddr_t) rte) return; /* There is one special case. If there is exactly one entry in the request, and it has a destination prefix of zero, a prefix length of zero, and a metric of infinity (i.e., 16), then this is a request to send the entire routing table. In that case, a call is made to the output process to send the routing table to the requesting address/port. */ if (lim == ((caddr_t) (rte + 1)) && IN6_IS_ADDR_UNSPECIFIED (&rte->addr) && rte->prefixlen == 0 && rte->metric == RIPNG_METRIC_INFINITY) { /* All route with split horizon */ ripng_output_process (ifp, from, ripng_all_route, ripng_split_horizon); } else { /* Except for this special case, processing is quite simple. Examine the list of RTEs in the Request one by one. For each entry, look up the destination in the router's routing database and, if there is a route, put that route's metric in the metric field of the RTE. If there is no explicit route to the specified destination, put infinity in the metric field. Once all the entries have been filled in, change the command from Request to Response and send the datagram back to the requestor. */ memset (&p, 0, sizeof (struct prefix_ipv6)); p.family = AF_INET6; for (; ((caddr_t) rte) < lim; rte++) { p.prefix = rte->addr; p.prefixlen = rte->prefixlen; apply_mask_ipv6 (&p); rp = route_node_lookup (ripng->table, (struct prefix *) &p); if (rp) { rinfo = rp->info; rte->metric = rinfo->metric; route_unlock_node (rp); } else rte->metric = RIPNG_METRIC_INFINITY; } packet->command = RIPNG_RESPONSE; ripng_send_packet ((caddr_t) packet, size, from, ifp); }}/* First entry point of reading RIPng packet. */int
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -