📄 riplib.c
字号:
FD_ZERO (&ibits); nfd = max (ripState.s, ripState.routeSocket) + 1; /* 1 + max (fd's) */ for (;;) { FD_SET (ripState.s, &ibits); FD_SET (ripState.routeSocket, &ibits); if (ripState.needupdate) { /* * Changes to the routing table entries occurred within the * mandatory (random) quiet period following an earlier * triggered update. Set the selection interval for incoming * messages to the remaining delay so that the pending * (cumulative) triggered update will be sent on schedule. */ pTimeout = &waittime; waittime = ripState.nextbcast; timevalsub (&waittime, &ripState.now); if (waittime.tv_sec < 0) { /* * The scheduled update time has passed. Just poll the * interface before sending the triggered update. */ waittime.tv_sec = 0; waittime.tv_usec = 0; } if (routedDebug) logMsg ("Pending dynamic update scheduled in %d/%d sec/usec\n", waittime.tv_sec, waittime.tv_usec, 0, 0, 0, 0); } else { /* * No triggered updates are pending. Wait for * messages indefinitely. */ pTimeout = (struct timeval *)NULL; } n = select (nfd, &ibits, 0, 0, pTimeout); if (n <= 0) { /* * No input received during specified interval: generate * (delayed) triggered update if needed. Ignore all other * errors (e.g. EINTR). */ if (n < 0) { if (errno == EINTR) continue; if (routedDebug) logMsg ("Error %d (%x) from select call", n, errno, 0, 0, 0, 0); } /* Block timer task to prevent overlapping updates. */ semTake (ripLockSem, WAIT_FOREVER); if (n == 0 && ripState.needupdate) { /* * The pending triggered update was not subsumed by a * regular update during the selection interval. Send it * and reset the update flag and timers. */ if (routedDebug) logMsg ("send delayed dynamic update\n", 0, 0, 0, 0, 0, 0); ripTimeSet (&ripState.now); toall (supply, RTS_CHANGED, (struct interface *)NULL); ripState.lastbcast = ripState.now; ripState.needupdate = 0; ripState.nextbcast.tv_sec = 0; } semGive (ripLockSem); continue; } ripTimeSet (&ripState.now); /* * Block the timer task to prevent overlapping updates or * route addition/deletion during * processing of RIP and route messages. */ semTake (ripLockSem, WAIT_FOREVER); /* If RIP messages have arrived, process them */ if (FD_ISSET (ripState.s, &ibits)) process (ripState.s); semGive (ripLockSem);#ifdef ROUTER_STACK /* If there are any routing messages, process them */ if (FD_ISSET (ripState.routeSocket, &ibits)) ripRouteMsgProcess ();#endif /* ROUTER_STACK */ } }void timevaladd (t1, t2) struct timeval *t1, *t2;{ t1->tv_sec += t2->tv_sec; if ((t1->tv_usec += t2->tv_usec) > 100000) { t1->tv_sec++; t1->tv_usec -= 1000000; }}void timevalsub (t1, t2) struct timeval *t1, *t2;{ t1->tv_sec -= t2->tv_sec; if ((t1->tv_usec -= t2->tv_usec) < 0) { t1->tv_sec--; t1->tv_usec += 1000000; }}/******************************************************************************** ripTimeSet - update a RIP timer** This routine sets the various RIP timers used to track periodic updates* to the elapsed time since startup. Because all events use relative* times, the actual (calendar) time is not necessary.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/void ripTimeSet ( struct timeval * pTimer /* destination for timestamp */ ) { int clockrate; ULONG tickcount; tickcount = tickGet (); clockrate = sysClkRateGet (); pTimer->tv_sec = tickcount / clockrate; pTimer->tv_usec = (1000000 * tickcount % clockrate) / clockrate; return; }void process (fd) int fd;{ struct sockaddr from; int fromlen, cc; union { char buf[MAXPACKETSIZE+1]; RIP_PKT rip; } inbuf; bzero ((char *)&from, sizeof (from)); for (;;) { fromlen = sizeof (from); cc = recvfrom (fd, (char *)&inbuf, sizeof (inbuf), 0, &from, &fromlen); if (cc <= 0) { if (cc < 0 && errno != EWOULDBLOCK) { if (routedDebug) logMsg ("Error %d (%x) reading RIP message.\n", cc, errno, 0, 0, 0, 0); } break; } if (fromlen != sizeof (struct sockaddr_in)) break; routedInput (&from, &inbuf.rip, cc); }}/******************************************************************************** _ripAddrsXtract - extract socket addresses** This routine is a copy of the rt_xaddrs() routine in rtsock.c* Copied here so that RIP can access it from a non-kernel domain* it basicaly fills in the rti_info array with pointers to the* sockaddr structures denoted by the rti_addrs field.* The sockaddr structures themselves start at <cp> and end at <cpLim>.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/void _ripAddrsXtract ( caddr_t cp, caddr_t cpLim, struct rt_addrinfo * pRtInfo ) { register struct sockaddr * pSockAddr; register int i; bzero ((char *)pRtInfo->rti_info, sizeof (pRtInfo->rti_info)); for (i = 0; (i < RTAX_MAX) && (cp < cpLim); i++) { if ((pRtInfo->rti_addrs & (1 << i)) == 0) continue; pRtInfo->rti_info[i] = pSockAddr = (struct sockaddr *)cp; if (pSockAddr->sa_len == 0) pRtInfo->rti_info[i] = NULL; ADVANCE (cp, pSockAddr); } }/******************************************************************************** ripAddrsXtract - extract socket address pointers from the route message** This routine extracts the socket addresses from the route message in * <pRtInfo> and uses the other parameters to return pointers to the * extracted messages.* \is* \i <pRtInfo>* Passes in a pointer to a route information message. * \i <pDstAddr> * Returns a pointer to the destination address.* \i <pNetmask> * Returns a pointer to the netmask.* \i <pGateway> * Returns a pointer to the gateway address.* \i <pOldGateway> * Returns a pointer to the OLD gateway address if it exists.* \ie* * If the route message doesn't specify an address, the corresponding* address pointer is set to NULL** RETURNS: N/A** ERRNO: N/A*/void ripAddrsXtract ( ROUTE_INFO * pRtInfo, /* Route information message */ struct sockaddr ** pDstAddr, /* Where to store the Destination addr pointer */ struct sockaddr ** pNetmask, /* Where to store the netmask pointer*/ struct sockaddr ** pGateway, /* Where to store the Gateway addr pointer */ struct sockaddr ** pOldGateway /* Where to store the Old gateway addr (if any) pointer */ ) { struct rt_addrinfo rtInfo; /* First extract pointers to the addresses into the info structure */ rtInfo.rti_addrs = pRtInfo->rtm.rtm_addrs; _ripAddrsXtract ((caddr_t)pRtInfo->addrs, (caddr_t)&pRtInfo->addrs[RTAX_MAX], &rtInfo); /* Now set the users's pointers to point to the addresses */ *pDstAddr = INFO_DST (&rtInfo); *pNetmask = INFO_MASK (&rtInfo); *pGateway = INFO_GATE (&rtInfo); *pOldGateway = INFO_AUTHOR (&rtInfo); }/******************************************************************************** ripSockaddrPrint - print a sockaddr structure** This routine is a copy of the db_print_sa() routine in if_ether.c* Copied here so that RIP can access it from a non-kernel domain.* It prints out the sockaddr structure pointed to by <pSockAddr>** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/void ripSockaddrPrint ( struct sockaddr * pSockAddr /* Sockaddr to be printed */ ) { int len; u_char * p; if (pSockAddr == 0) { printf ("[NULL]\n"); return; } p = (u_char *)pSockAddr; len = pSockAddr->sa_len; printf ("["); while (len > 0) { printf ("%d", *p); p++; len--; if (len) printf (","); } printf ("]\n"); }#ifdef ROUTER_STACK/***************************************************************************** ripRouteMsgProcess - Process the routing socket messages** This function retrieves the messages from the routing sockets * and processes them. It handles the following messages:** RTM_IFINFO:* This message indicates if an interface has been brought up or down.* If the interface is brought up, this routine does the following:* For all interfaces that match the name, it marks the interface UP* and adds the interface route.* Then it calls the routedIfInit() call to pick up any addresses that* were added to the interface when the interface was down* If the interface is brought down, this routine does the following:* For all interfaces that match the name, it marks the interface DOWN.* Routes passing through the interface are deleted except the* routes we learned through the Routing socket messages. Those routes
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -