📄 riplib.c
字号:
* then mark it as primary */ if (pRtEntry != NULL && ripRouteSame (pRtEntry, pDstAddr, pNetmask, pGateway)) { if (routedDebug) logMsg ("RTM_NEWIPROUTE: restoring primary route\n", 0, 0, 0, 0, 0, 0); pRtEntry->rt_state |= RTS_PRIMARY; } /* Now release the semaphore we took earlier */ semGive (ripLockSem); }addIt: /* * Now set the route hook flag to signify whether it * is an add operation or a change operation. * Note that we can get here from change processing too. * Also we treat RTM_NEWIPROUTE as a change since it is * not a new route that is being added to the system. */ hookFlag = (cmd == RTM_ADD || cmd == RTM_ADDEXTRA) ? 0 : RIP_ROUTE_CHANGE_RECD; /* * Call the user hook routine if installed. If the routine * returns a metric less than infinity, add the route to * our table, else just ignore it. The user is responsible * for setting the metric of the route. In case he forgets * to assign a valid metric, assign a default metric of 1 */ if (ripState.pRouteHook == NULL) break; if ((metric = (ripState.pRouteHook) (&msg.rtMsg, routeProto, primaryRoute, hookFlag)) >= HOPCNT_INFINITY) { /* Take the semaphore to lock the RIP timer task out */ semTake (ripLockSem, WAIT_FOREVER); pRtEntry = rtlookup (pDstAddr); /* * If we have the exact same route in our table, * then delete it as the user doesn't want it. */ if (pRtEntry != NULL && ripRouteSame (pRtEntry, pDstAddr, pNetmask, pGateway)) { if (routedDebug) logMsg ("ripRouteMsgProcess:cmd = %s: deleting primary" "route\n", (int)(rtmMessages [cmd]), 0, 0, 0, 0, 0); rtdelete (pRtEntry); } /* Now release the semaphore we took earlier */ semGive (ripLockSem); break; } if (metric < 0) metric = 1; /* Take the semaphore to lock the RIP timer task out */ semTake (ripLockSem, WAIT_FOREVER); /* * Check if we already have an entry for the specified * destination. If we do and it is a RIP route * (RTS_OTHER not set) or if the route belongs to another * protocol, but has a higher or same metric than this new * route, delete the old route. We always give precedence * to OTHER routes over RIP routes. In any case, we * do not allow an interface route to be replaced. Also * if we have the same route and its metric is being changed * we need to record that change. For simplicity, we just * delete the old route and add the new one. */ pRtEntry = rtlookup (pDstAddr); if ((pRtEntry == NULL) || (!(pRtEntry->rt_state & RTS_INTERFACE) && (((pRtEntry->rt_state & RTS_OTHER) == 0) || (pRtEntry->rt_metric >= metric) || ripRouteSame (pRtEntry, pDstAddr, pNetmask, pGateway)))) { if (pRtEntry) rtdelete (pRtEntry); flags = RTS_OTHER; /* Record whether this route is the primary route or not */ if (primaryRoute) flags |= RTS_PRIMARY; rtadd (pDstAddr, pGateway, metric, flags, pNetmask, routeProto, 0, 0, NULL); if (routedDebug) logMsg ("%s: Added new route\n", (int)rtmMessages [cmd], 0, 0, 0, 0, 0); } /* Now release the semaphore we took earlier */ semGive (ripLockSem); break; case RTM_CHANGE: /* Primary route changing */ case RTM_NEWCHANGE: /* Duplicate route changing */ if (msg.rtMsg.rtm.rtm_errno != 0) { if (routedDebug) logMsg ("ignore route message %s for index %d" " error = %d\n", (int)rtmMessages [cmd], index, msg.rtMsg.rtm.rtm_errno, 0, 0, 0); break; } /* * Get the address of the old gateway. This information * is only available for the RTM_NEWCHANGE and not for * RTM_CHANGE (for compatibility reasons) */ if (cmd == RTM_NEWCHANGE) { pOldGateway = INFO_AUTHOR (&rtInfo); /* * If Gateway didn't change, set old gateway to * the previous gateway address, so that ripRouteSame * can work properly. */ if (pOldGateway == NULL) pOldGateway = pGateway; if (pOldGateway == NULL) { /* * This is a route change for a duplicate route * for which the gateway didn't change. * Also, we don't have enough information * to determine if we have this particular route * in our cache. We need a gateway * address to identify a duplicate route. * Since we can't do that, simply exit. */ if (routedDebug) logMsg ("RTM_NEWCHANGE: gateway not specified. " "Doing nothing.\n", 0, 0, 0, 0, 0, 0); break; } } else pOldGateway = NULL; if (routedDebug) { logMsg ("RIP: %s received\n", (int)rtmMessages [cmd],0,0,0,0,0); ripSockaddrPrint (pDstAddr); ripSockaddrPrint (pNetmask); ripSockaddrPrint (pGateway); logMsg ("RIP: %s received: old Gateway addr\n", (int)rtmMessages [cmd],0,0,0,0,0); ripSockaddrPrint (pOldGateway); logMsg ("RIP: new metric %d\n", msg.rtMsg.rtm.rtm_rmx.rmx_hopcount,0,0,0,0,0); } /* * If the route was installed by us or was an interface * route, ignore it. Nobody should be changing this route. */ routeProto = RT_PROTO_GET (pDstAddr); if (routeProto == M2_ipRouteProto_rip || routeProto == M2_ipRouteProto_local) break; /* * The destination sockaddr structure has the * protocol value set. Make it zero since * we compare the entire sockaddr structure at other * places (input.c for example) that expect the * standard fields to be zero. * We set the gateway sockaddr fields to be zero * too (just being paranoid, in case they aren't already zero) * as rtlookup() expects it to be zero. Do the same * for the TOS value too. * We store the proto value anyway in the rtentry * structure. */ if (pGateway) { RT_PROTO_SET (pGateway, 0); TOS_SET (pGateway, 0); } RT_PROTO_SET (pDstAddr, 0); TOS_SET (pDstAddr, 0); /* Take the semaphore to lock the RIP timer task out */ semTake (ripLockSem, WAIT_FOREVER); /* * Check if we have this route in our table. * If we have it, * make sure it is the exact * same route: * same dst, gateway and netmask values * same routing protocol * * If we know about this route, record the gateway change, * if any. If the hop count field was modified, then * that indicates that the RIP metric was stored in that * field; so we copy the metric from that field, * else we call the user hook for a new metric. * If they return a metric >= HOPCNT_INFINITY we delete the * route. else we update the metric. * Note that pOldGateway would be NULL if the primary route * is being changed. We account for that in the * ripRouteSame routine by checking if the route we have * is the primary route * * If we don't have the route in our table, call the user * hook to decide if they want us to propagate this route. */ pRtEntry = rtlookup (pDstAddr); if (pRtEntry && ((pRtEntry->rt_state & RTS_OTHER) != 0) && (pRtEntry->rt_proto == routeProto) && ripRouteSame (pRtEntry, pDstAddr, pNetmask, pOldGateway)) { /* If the gateway has changed, record the change */ if (pGateway && !equal (&pRtEntry->rt_router, pGateway)) { /* Now record the new gateway and its interface */ pRtEntry->rt_router = *pGateway; pRtEntry->rt_ifp = ripIfWithDstAddr (&pRtEntry->rt_router, NULL); if (pRtEntry->rt_ifp == 0) pRtEntry->rt_ifp = ripIfWithNet (&pRtEntry->rt_router); pRtEntry->rt_state |= RTS_CHANGED; if (routedDebug) logMsg ("%s: Changed gateway\n", (int)rtmMessages [cmd], 0, 0, 0, 0, 0); } /* If the metric changed, record it. */ if ((msg.rtMsg.rtm.rtm_inits & RTV_HOPCOUNT) != 0) { pRtEntry->rt_metric = msg.rtMsg.rtm.rtm_rmx.rmx_hopcount; pRtEntry->rt_state |= RTS_CHANGED; if (pRtEntry->rt_metric >= HOPCNT_INFINITY) { /* The user wants the route deleted. Do so */ rtdelete (pRtEntry); } } else if (ripState.pRouteHook != NULL) { /* Allow the use to specify a new metric */ metric = (ripState.pRouteHook) (&msg.rtMsg, routeProto, (cmd == RTM_CHANGE), RIP_ROUTE_CHANGE_RECD); /* If the user wants the route to be deleted, do so */ if (metric >= HOPCNT_INFINITY) { pRtEntry->rt_state |= RTS_CHANGED; rtdelete (pRtEntry); } else if (metric > 0) { /* Record the metric change */ pRtEntry->rt_metric = metric; pRtEntry->rt_state |= RTS_CHANGED; } } } else { /* * This might be a route that was duplicate, but * because it's weight changed for the better, it became * primary. Or it just might be a route that we ere told to * ignore earlier on, but since things have changed, * Allow the user to decide if he wants this * route to be propagated. */ if (routedDebug) logMsg ("%s: Trying to add new route\n", (int)rtmMessages [cmd], 0, 0, 0, 0, 0); semGive (ripLockSem); primaryRoute = (cmd == RTM_CHANGE) ? TRUE : FALSE; goto addIt; } semGive (ripLockSem); break; case RTM_OLDIPROUTE: if (routedDebug) { logMsg ("RIP: %s received for index %d\n", (int)rtmMessages [cmd], index, 0, 0, 0, 0); ripSockaddrPrint (pDstAddr); ripSockaddrPrint (pNetmask); ripSockaddrPrint (pGateway); } /* * If the route was installed by us or is an interface * route, ignore it. We don't care about these routes. */ routeProto = RT_PROTO_GET (pDstAddr); if (routeProto == M2_ipRouteProto_rip || routeProto == M2_ipRouteProto_local) break; /* * The destination sockaddr structure has
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -