📄 riplib.c
字号:
extern STATUS ripLeakHook(); ripState.msg = (RIP_PKT *)ripState.packet; /* Fake out getservbyname. */ ripState.port = htons (RIP_PORT); ripState.addr.sin_family = AF_INET; ripState.addr.sin_port = ripState.port; ripState.addr.sin_addr.s_addr = INADDR_ANY; ripState.s = getsocket (AF_INET, SOCK_DGRAM, &ripState.addr); if (ripState.s < 0) { if (routedDebug) logMsg ("Unable to get input/output socket.\n", 0, 0, 0, 0, 0, 0); return (ERROR); } ripState.supplier = supplier; ripState.gateway = gateway; /* VxWorks specific setup. */ ripState.timerDog = wdCreate (); ripState.timerSem = semBCreate (SEM_Q_FIFO, SEM_EMPTY); if (ripState.timerSem == NULL) { if (routedDebug) logMsg ("Error creating timer semaphore.\n", 0, 0, 0, 0, 0, 0); close (ripState.s); wdDelete (ripState.timerDog); return (ERROR); } ripLockSem = semBCreate(SEM_Q_FIFO, SEM_FULL); if (ripLockSem == NULL) { if (routedDebug) logMsg ("Error creating mutex semaphore.\n", 0, 0, 0, 0, 0, 0); close (ripState.s); wdDelete (ripState.timerDog); semDelete (ripState.timerSem); return (ERROR); } /* * Setup the hash tables for route entries and create entries to * access the directly connected networks through the current * interfaces. */ routedTableInit(); if (routedIfInit () == ERROR) { if (routedDebug) logMsg ("Error building interface list.\n", 0, 0, 0, 0, 0, 0); close (ripState.s); wdDelete (ripState.timerDog); semDelete (ripState.timerSem); semDelete (ripLockSem); return (ERROR); } /* * If configured as a gateway to the wider Internet, add an internal * entry to the RIP routing table so that any default routes received * will be ignored. */ if (ripState.gateway > 0) rtdefault(); if (ripState.supplier < 0) ripState.supplier = 0; /* * Send a request message over all available interfaces * to retrieve the tables from neighboring RIP routers. */ query->rip_cmd = RIPCMD_REQUEST; query->rip_vers = ripState.version; if (sizeof(query->rip_nets[0].rip_dst.sa_family) > 1) /* XXX */ query->rip_nets[0].rip_dst.sa_family = htons ( (u_short)AF_UNSPEC); else query->rip_nets[0].rip_dst.sa_family = AF_UNSPEC; query->rip_nets[0].rip_metric = htonl ( (u_long)HOPCNT_INFINITY); toall (sndmsg, 0, NULL); /* Start the watchdog used by the timer task to send periodic updates. */ ripTimerArm (ripState.timerRate); /* Create the timer task. */ ripState.ripTimerTaskId = taskSpawn (RIP_TIMER, _ripTimerTaskPriority, _ripTimerTaskOptions, _ripTimerTaskStackSize, ripTimer, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); if (ripState.ripTimerTaskId == ERROR) { if (routedDebug) logMsg ("Error creating timer task.\n", 0, 0, 0, 0, 0, 0); close (ripState.s); wdCancel (ripState.timerDog); wdDelete (ripState.timerDog); semDelete (ripState.timerSem); semDelete (ripLockSem); return (ERROR); } FD_ZERO(&ibits); nfd = ripState.s + 1; /* 1 + max(fd's) */ for (;;) { FD_SET (ripState.s, &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 deletions during message processing. */ semTake (ripLockSem, WAIT_FOREVER); if (ibits.fds_bits[ripState.s/32] & (1 << ripState.s)) process(ripState.s); semGive (ripLockSem); /* XXX: handle ICMP redirects */ } }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", 0, 0, 0, 0, 0, 0); } break; } if (fromlen != sizeof (struct sockaddr_in)) break; routedInput(&from, &inbuf.rip, cc); }}int getsocket(domain, type, sin) int domain, type; struct sockaddr_in *sin;{ int sock, on = 1; if ((sock = socket(domain, type, 0)) < 0) { if (routedDebug) logMsg ("Error creating socket.\n", 0, 0, 0, 0, 0, 0); return (-1); }#ifdef SO_BROADCAST if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&on, sizeof (on)) < 0) { if (routedDebug) logMsg ("error setting SO_BROADCAST option", 0, 0, 0, 0, 0, 0); close(sock); return (-1); }#endif#ifdef SO_RCVBUF for (on = BUFSPACE; ; on -= 1024) { if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&on, sizeof (on)) == 0) break; if (on <= 8*1024) { if (routedDebug) logMsg ("unable to set SO_RCVBUF option", 0, 0, 0, 0, 0, 0); break; } } if (routedDebug) logMsg ("Receive buffer size %d.\n", on, 0, 0, 0, 0, 0);#endif if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) { if (routedDebug) logMsg ("error binding socket.\n", 0, 0, 0, 0, 0, 0); close(sock); return (-1); } on = 1; if (ioctl(sock, FIONBIO, (int) &on) == -1) if (routedDebug) logMsg ("error setting O_NONBLOCK option.\n", 0, 0, 0, 0, 0, 0); /* set the socketoption to join the MULTICAST group */ if (ripState.multicast) { ripSetInterfaces(sock, (UINT32)RIP_MCAST_ADDR); } return (sock);}/******************************************************************************** ripTimerArm - arm the timeout to do routing updates** This routine starts (or resets) the watchdog timer to trigger periodic* updates at the assigned interval.** RETURNS: N/A** NOMANUAL */void ripTimerArm ( long timeout /* update interval in seconds */ ) { int ticks; ticks = timeout * sysClkRateGet(); wdStart (ripState.timerDog, ticks, semGive, (int)ripState.timerSem); }/******************************************************************************** ripSplitPacket - split up a rip packet for version 2** INTERNAL ** The <orig> parameter accesses a single route entry within the payload* of a RIP message. In order for the rtadd() routine to store the data in* the expected format, the sin_port and sin_zero fields of the overlayed* structure (which correspond to the route tag, subnet mask, and next hop* values) must be cleared after that data is extracted.** NOMANUAL*/void ripSplitPacket ( struct interface* pIfp, struct sockaddr_in *src, /* Address of router which sent update. */ struct sockaddr* orig, struct sockaddr* gateway, struct sockaddr* netmask ) { BOOL noGate = FALSE; BOOL noMask = FALSE; char zero[4];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -