📄 riplib.c
字号:
* will not be advertised though.* RTM_NEWADDR:* Calls the routedIfInit() routine to pick up the new address. If the* interface is down, routedIfInit() doesn't do anything. The new address* is picked up when the interface comes back up.* RTM_DELADDR:* Deletes all routes that pass though the interface whose address* matches the deleted address and then deletes the interface structure* Deleting the interface structure would cause the MIB settings for* the structure to be lost, but that is OK as the MIB settings do* not apply to an interface name, but to an interface addr. Thus if* the address goes away, it is reasonable to remove whatever settings* were associated with it.* RTM_ADD:* RTM_ADDEXTRA:* This message indicates that a route has been added. If the route * is installed by us or the system (interface route) it is ignored.* All other routes are passed to the user route handler hook routine* if it is installed. If the handler is not installed the route is* ignored. If the handler returns a metric < HOPCNT_INFINITY, then we* install the route if none exists already. If a route already exists* for the same destination then we use the following logic to determine* if we need to replace the old route with the new one:* If the old route is a RIP route, we replace it with the new one* If the metric of the old route is greater than or equal to* the metric of the new route, then we replace the old route.* RTM_ADD signifies that it the route is the primary route and* RTM_ADDEXTRA signifies a duplicate route. We don't prefer* one over the other and let the user route hook do that. * RTM_NEWIPROUTE:* This message indicates that a formerly duplicate route has been* promoted to being a primary route because either the previously* primary route was deleted or demoted because of weight change.* We treat this just as we would treat the RTM_ADD command, except* that we mark the previous primary route as non-primary.* RTM_DELETE:* RTM_DELEXTRA:* This message indicates that the route has been deleted. Again if* the route has been installed by us or by the system, we ignore it,* else if the exact same route exists in our table we delete it.* RTM_DELETE signifies that the route is the primary route and* RTM_DELEXTRA signifies a duplicate route. * RTM_OLDIPROUTE:* This message indicates that a formerly primary route has been* demoted to being a duplicate route because either a new* primary route was added or because of weight change.* If we have this route in our cache we mark it non-primary.* * RTM_CHANGE:* RTM_NEWCHANGE:* This message indicates that either the route metric and or the* route gateway has been changed. We first check if we know about this* route. If we don't, we ignore it, else if it is only a metric change,* we record that in our copy of the route. If the gateway has changed,* we invoke the user route hook routine, if installed, to provide* us an alternate metric, else we use the metric in the route. Finally* we change the gateway in our copy of the route.* RTM_REDIRECT:* This message indicates a gateway change caused by an ICMP redirect* message. This should happen only with static routes. * We simply invoke the route Hook if it is installed to notify the* user of the redirect. If is the user's responsibility to deal* with the redirect message.** RETURNS: N/A** NOMANUAL*/LOCAL void ripRouteMsgProcess (void) { int cmd; int flags; int routeProto; int metric; int hookFlag; long count; u_short index; struct rt_addrinfo rtInfo; struct sockaddr * pDstAddr = NULL; struct sockaddr * pNetmask = NULL; struct sockaddr * pGateway = NULL; struct sockaddr * pOldGateway; struct interface * pIf; struct rt_entry * pRtEntry; BOOL primaryRoute; union { ROUTE_INFO rtMsg; /* Route message */ struct if_msghdr ifMsg; /* Interface message header */ struct { struct ifa_msghdr ifa; struct sockaddr addrs [RTAX_MAX]; } ifaMsg; /* Interface address message */ } msg; /* Routing socket message */ /* * Receive the messages from the routing socket. Return when there * are no more */ FOREVER { count = recv (ripState.routeSocket, (char *)&msg, sizeof (msg), 0); if (count <= 0) { if (count < 0 && errno != EWOULDBLOCK) if (routedDebug) logMsg ("Error %d (%x) reading Route message.\n", count, errno, 0, 0, 0, 0); return; } /* Skip if not the correct version of routing socket message */ if (msg.rtMsg.rtm.rtm_version != RTM_VERSION) { logMsg ("Bogus routing message version %d\n", msg.rtMsg.rtm.rtm_version, 0, 0, 0, 0, 0); continue; } cmd = msg.rtMsg.rtm.rtm_type; /* * Retrieve the interface index and validate parameters * based on the command value */ switch (cmd) { case RTM_ADD: /* Fall through */ case RTM_DELETE: /* Fall through */ case RTM_CHANGE: /* Fall through */ case RTM_REDIRECT: /* Fall through */ case RTM_ADDEXTRA: /* Fall through */ case RTM_DELEXTRA: /* Fall through */ case RTM_NEWCHANGE: /* Fall through */ case RTM_NEWIPROUTE: /* Fall through */ case RTM_OLDIPROUTE: index = msg.rtMsg.rtm.rtm_index; if (msg.rtMsg.rtm.rtm_flags & RTF_LLINFO) { if (routedDebug) logMsg ("ignore route message %s for ifindex %d ARP\n", (int)(rtmMessages [cmd]), index, 0, 0, 0, 0); continue; } /* Now extract the sockaddr structures into the rtInfo array */ rtInfo.rti_addrs = msg.rtMsg.rtm.rtm_addrs; _ripAddrsXtract ((caddr_t)msg.rtMsg.addrs, (caddr_t)&msg.rtMsg.addrs[RTAX_MAX], &rtInfo); /* Set the destination, netmask and gateway address pointers */ pDstAddr = INFO_DST (&rtInfo); pGateway = INFO_GATE (&rtInfo); pNetmask = INFO_MASK (&rtInfo); /* So some sanity checking on the addresses */ /* No destination address ? Reject it */ if (pDstAddr == 0) { if (routedDebug) logMsg ("ignore route message %s for ifindex %d without" "dst\n", (int)(rtmMessages [cmd]), index, 0, 0, 0, 0); continue; } /* Destination address doesn't belong to the Internet family */ if (pDstAddr->sa_family != AF_INET) { if (routedDebug) logMsg ("ignore route message %s for ifindex %d for AF %d\n", (int)(rtmMessages [cmd]), index, pDstAddr->sa_family, 0, 0, 0); continue; } /* Destination address is a multicast address ? Reject it */ if (IN_MULTICAST (ntohl (S_ADDR (pDstAddr)))) { if (routedDebug) logMsg ("ignore route message %s for ifindex %d multicast\n", (int)(rtmMessages [cmd]), index, 0, 0, 0, 0); continue; } /* * If the gateway address is AF_LINK, this is an interface * route. Ignore it. */ if (pGateway != NULL) { if (pGateway->sa_family == AF_LINK) { if (routedDebug) { logMsg ("Got interface address in %s for ifindex %d\n", (int)(rtmMessages [cmd]), index, 0, 0, 0, 0); ripSockaddrPrint (pDstAddr); ripSockaddrPrint (pNetmask); ripSockaddrPrint (pGateway); } continue; } } /* * If the gateway flag is not set, if must be an * interface route. Ignore it. */ if ((msg.rtMsg.rtm.rtm_flags & RTF_GATEWAY) == 0) { if (routedDebug) { logMsg ("got i/f route message %s for ifindex %d ARP\n", (int)(rtmMessages [cmd]), index, 0, 0, 0, 0); ripSockaddrPrint (pDstAddr); ripSockaddrPrint (pNetmask); ripSockaddrPrint (pGateway); } continue; } break; case RTM_NEWADDR: /* Fall through */ case RTM_DELADDR: index = msg.ifaMsg.ifa.ifam_index; /* * Now extract the sockaddr structures into the * rtInfo array */ rtInfo.rti_addrs = msg.ifaMsg.ifa.ifam_addrs; _ripAddrsXtract ((caddr_t)msg.ifaMsg.addrs, (caddr_t)&msg.ifaMsg.addrs[RTAX_MAX], &rtInfo); break; default: index = msg.ifMsg.ifm_index; break; } if (routedDebug) { if (cmd <= (sizeof (rtmMessages) / sizeof (rtmMessages[0]))) logMsg ("\nripRouteMsgProcess:cmd = %s Interface index = %d\n", (int)(rtmMessages [cmd]), index, 0, 0, 0, 0); else logMsg ("\nripRouteMsgProcess:cmd = %d Interface index = %d\n", cmd, index, 0, 0, 0, 0); } /* Now process the actual commands */ switch (cmd) { case RTM_ADD: case RTM_ADDEXTRA: case RTM_NEWIPROUTE: 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; } 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 already know about it */ routeProto = RT_PROTO_GET (pDstAddr); if (routeProto == M2_ipRouteProto_rip || routeProto == M2_ipRouteProto_local) break; primaryRoute = (cmd == RTM_ADDEXTRA) ? FALSE : TRUE; /* * 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. */ RT_PROTO_SET (pGateway, 0); TOS_SET (pGateway, 0); RT_PROTO_SET (pDstAddr, 0); TOS_SET (pDstAddr, 0); /* * If a new primary route is coming into being, * we should mark our primary route, if any, as non-primary * We don't need to do this for RTM_ADD as it will be preceded * by a RTM_OLDIPROUTE if there was a pre existing primary * route */ if (cmd == RTM_NEWIPROUTE) { /* Take the semaphore to lock the RIP timer task out */ semTake (ripLockSem, WAIT_FOREVER); pRtEntry = rtlookup (pDstAddr); if (pRtEntry != NULL && ripRouteSame (pRtEntry, pDstAddr, pNetmask, NULL)) { if (routedDebug) logMsg ("RTM_NEWIPROUTE: demoting primary route\n", 0, 0, 0, 0, 0, 0); pRtEntry->rt_state &= ~RTS_PRIMARY; } /* * If we have the exact same route in our table,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -