📄 input.c
字号:
if ( ((RIP2PKT *)n)->subnet != 0) { pErrorIfp->ifStat.rip2IfStatRcvBadRoutes++; continue; } if ( ((RIP2PKT *)n)->gateway != 0) { pErrorIfp->ifStat.rip2IfStatRcvBadRoutes++; continue; } } /* * Ignore any entry with an inappropriate address. * The receiving interface is used to detect broadcast * addresses if no netmask is present in the route update. */ if ( ((*afp->af_checkhost)(&n->rip_dst, ifp)) == 0) { if (routedDebug) logMsg ("bad host in route from %s (af %d)\n", (int)(*afswitch[from->sa_family].af_format)(from), from->sa_family, 0, 0, 0, 0); pErrorIfp->ifStat.rip2IfStatRcvBadRoutes++; continue; } if ((n->rip_metric == 0) || ((unsigned) n->rip_metric > HOPCNT_INFINITY)) { if (memcmp(from, &badfrom2, sizeof(badfrom2)) != 0) { if (routedDebug) logMsg ("bad metric (%d) from %s\n", n->rip_metric, (int)(*afswitch[from->sa_family].af_format)(from), 0, 0, 0, 0); badfrom2 = *from; } pErrorIfp->ifStat.rip2IfStatRcvBadRoutes++; continue; } rt = rtlookup (&n->rip_dst); if (rt == 0 || (rt->rt_state & (RTS_INTERNAL|RTS_INTERFACE)) == (RTS_INTERNAL|RTS_INTERFACE)) { /* * If we're hearing a logical network route * back from a peer to which we sent it, * ignore it. */ if (rt && rt->rt_state & RTS_SUBNET && (*afp->af_sendroute)(rt, from, ifp)) { pErrorIfp->ifStat.rip2IfStatRcvBadRoutes++; continue; } /* * Adjust metric according to incoming interface. */ if ((unsigned)n->rip_metric < HOPCNT_INFINITY) { /* * Look for an equivalent route that * includes this one before adding * this route. */ rt = rtfind(&n->rip_dst); if ((rt && equal(from, &rt->rt_router)) && (rt->rt_metric <= n->rip_metric)) continue; n->rip_metric += ifp->int_metric; if (rip->rip_vers < 2) { rtadd (&n->rip_dst, from, n->rip_metric, 0, NULL); } else { ripSplitPacket (ifp, (struct sockaddr_in *)from, &n->rip_dst, &gateway, &netmask); if (((struct sockaddr_in *)&netmask)->sin_addr.s_addr == -1) { pErrorIfp->ifStat.rip2IfStatRcvBadRoutes++; continue; } /* * RFC 1723, Section 3.4: check to see that the * gateway is directly reachable. If not, treat * that value as 0.0.0.0 by using the originator * as the gateway. */ if ( (((struct sockaddr_in *)&gateway)->sin_addr.s_addr & htonl (ifp->int_subnetmask)) != (((struct sockaddr_in *)&ifp->int_addr)->sin_addr.s_addr & htonl (ifp->int_subnetmask))) { ((struct sockaddr_in *)&gateway)->sin_addr.s_addr = ((struct sockaddr_in *)from)->sin_addr.s_addr; } rtadd(&n->rip_dst, &gateway, n->rip_metric, 0, &netmask); } changes++; } continue; } /* * Update if from gateway and different, * shorter, or equivalent but old route * is getting stale. */ /* * If this was a pre-existinng route then we can * update it to be "infinite" and should. * ANVL 7.13. */ if ((unsigned) n->rip_metric < HOPCNT_INFINITY) n->rip_metric += ifp->int_metric; if (n->rip_metric > HOPCNT_INFINITY) { pErrorIfp->ifStat.rip2IfStatRcvBadRoutes++; continue; } if (equal(from, &rt->rt_router)) { if (n->rip_metric != rt->rt_metric) { if (rip->rip_vers > 1) { ripSplitPacket(ifp, (struct sockaddr_in *)from, &n->rip_dst, &gateway, &netmask); rtchange(rt, &gateway, n->rip_metric, &netmask); } else { rtchange(rt, from, n->rip_metric, NULL); } changes++; rt->rt_timer = 0; if (rt->rt_metric >= HOPCNT_INFINITY) rt->rt_timer = ripState.expire; else if (rt->pKernelRt) /* Set age for IP group MIB. */ rt->pKernelRt->rt_mod = tickGet (); } else if (rt->rt_metric < HOPCNT_INFINITY) { rt->rt_timer = 0; if (rt->pKernelRt) /* Update age for IP group MIB. */ rt->pKernelRt->rt_mod = tickGet (); } } else if ((unsigned) n->rip_metric < rt->rt_metric || (rt->rt_metric == n->rip_metric && rt->rt_timer > (ripState.expire/2) && (unsigned) n->rip_metric < HOPCNT_INFINITY)) { if (rip->rip_vers > 1) { ripSplitPacket(ifp, (struct sockaddr_in *)from, &n->rip_dst, &gateway, &netmask); rtchange(rt, &gateway, n->rip_metric, &netmask); } else { rtchange(rt, from, n->rip_metric, NULL); } changes++; rt->rt_timer = 0; if (rt->pKernelRt) /* Update age for IP group MIB. */ rt->pKernelRt->rt_mod = tickGet (); } } break; default: /* * Ignore any unrecognized commands. Return from the routine * to prevent any possibility of scheduling a triggered update. */ pErrorIfp->ifStat.rip2IfStatRcvBadPackets++; return; } /* * This section of code schedules triggered updates whenever entries in * the routing table change. No updates are sent for silent RIP * configurations and are also suppressed if a regular update will * occur within the next MAX_WAITTIME seconds. */ if (changes && ripState.supplier && ripState.now.tv_sec - ripState.lastfullupdate.tv_sec < ripState.supplyInterval - MAX_WAITTIME) { /* * No regular update is imminent. Check the elapsed time since * the previous (regular or triggered) update and the time limit * of the "nextbcast" quiet period which restricts the update * frequency. */ if (ripState.now.tv_sec - ripState.lastbcast.tv_sec >= MIN_WAITTIME && (ripState.nextbcast.tv_sec < ripState.now.tv_sec)) { /* * All conditions have been met. Send a triggered update over the * interfaces which did not receive the RIP response. The message * sent over each interface only includes routes which changed * since the last message sent. */ if (routedDebug) logMsg ("send dynamic update\n", 0, 0, 0, 0, 0, 0); ifp->ifStat.rip2IfStatSentUpdates++; toall (supply, RTS_CHANGED, ifp); ripState.lastbcast = ripState.now; ripState.needupdate = 0; ripState.nextbcast.tv_sec = 0; } else { /* * The triggered update can't be sent because of frequency * limitations imposed to prevent excessive network traffic. * Set the delayed update indicator so that the update will * be sent when possible. */ ripState.needupdate++; } if (ripState.nextbcast.tv_sec == 0) { /* * Select the earliest possible time for the next triggered * update. A random value is used to avoid periodic network * congestion from synchronized routers. */ u_long delay = RANDOMDELAY(); ripState.nextbcast.tv_sec = delay / 1000000; ripState.nextbcast.tv_usec = delay % 100000; timevaladd (&ripState.nextbcast, &ripState.now); /* * If the earliest allowable update occurs within MIN_WAITTIME * seconds before the next regular update, force the delay past * that point to avoid a redundant triggered update. */ if (ripState.nextbcast.tv_sec > ripState.lastfullupdate.tv_sec + ripState.supplyInterval - MIN_WAITTIME) { ripState.nextbcast.tv_sec = ripState.lastfullupdate.tv_sec + ripState.supplyInterval + 1; } } } }/* * This pseudo-random number generator restricts the frequency of triggered * updates. It was plagiarized shamelessly from FreeBSD 2.1.7 where it was * used for the same purpose by routed. */LOCAL u_long ripRandTime (void) { register long x, hi, lo, t; /* * Compute x[n + 1] = (7^5 * x[n]) mod (2^31 - 1). * From "Random number generators: good ones are hard to find", * Park and Miller, Communications of the ACM, vol. 31, no. 10, * October 1988, p. 1195. */ x = ripRandTimeSeed; hi = x / 127773; lo = x % 127773; t = 16807 * lo - 2836 * hi; if (t <= 0) t += 0x7fffffff; ripRandTimeSeed = t; return (t); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -