📄 riplib.c
字号:
bzero ( (char *)&zero, 4); /* Check to see if the packet has the proper info. */ if (bcmp((orig->sa_data + RIP2_MASK_OFFSET), (char *)&zero, 4) == 0) noMask = TRUE; if (bcmp((orig->sa_data + RIP2_GATE_OFFSET), (char *)&zero, 4) == 0) noGate = TRUE; /* * Clear the provided storage for packet data. The rtadd routine used * later requires zero values for all unused fields for correct * operation of the protocol. Later queries will fail if this condition * is not met. */ bzero ( (char *)gateway, sizeof(gateway)); bzero ( (char *)netmask, sizeof(netmask)); /* Duplicate the shared parameters from the current route entry. */ gateway->sa_family = orig->sa_family; gateway->sa_len = orig->sa_len; netmask->sa_family = orig->sa_family; netmask->sa_len = orig->sa_len; /* Extract the data from the original packet. */ if (noGate) { /* * RFC 1723, Section 3.4: If a value of 0.0.0.0 is given in the next * hop field, use the originator of the RIP advertisement as the * gateway. */ bcopy ( (char *)&(src->sin_addr.s_addr), (char *)gateway->sa_data + 2, 4); } else bcopy ( (char *)(orig->sa_data + RIP2_GATE_OFFSET), (char *)gateway->sa_data + 2, 4); if (noMask) bcopy ( (char *)&pIfp->int_subnetmask, (char *)netmask->sa_data + 2, 4); else bcopy ( (char *)(orig->sa_data + RIP2_MASK_OFFSET), (char *)netmask->sa_data + 2, 4); /* * Clear the fields in the original data now that the values have been * copied. This step converts that structure into a format suitable * for use with the rtadd() function. */ /* Erase the route tag (sin_port field). */ bzero ( (char *)orig->sa_data, 2); /* Erase the adjacent subnet mask and next hop values (sin_zero field). */ bzero ( (char *)(orig->sa_data + RIP2_MASK_OFFSET), 8); return; }/******************************************************************************** ripRouteToAddrs - convert a route entry into separate sockaddr_in structures** This routine takes a pointer to an rt_entry and parses it out into* three sockaddr_in structures. pDsin contains the destination, pGsin contains* the gateway and pNsin contains the subnetmask.** RETURNS: N/A** NOMANUAL*/void ripRouteToAddrs ( struct rt_entry* pRoute, /* Route to convert. */ struct sockaddr_in** ppDsin, /* Destination sin. */ struct sockaddr_in** ppGsin, /* Gateway sin. */ struct sockaddr_in** ppNsin /* Netmask sin. */ ) { if (ppDsin != NULL) *ppDsin = (struct sockaddr_in *) &(pRoute->rt_dst); if (ppGsin != NULL) *ppGsin = (struct sockaddr_in *) &(pRoute->rt_router); if (ppNsin != NULL) *ppNsin = (struct sockaddr_in *) &(pRoute->rt_netmask); }/******************************************************************************** ripBuildPacket - this routine builds a packet from the route passed** This routine takes the routing entry that we are passed and properly* fills the fields in the packet. If RIP version 1 packets are requested,* then the sections that must be zero are left alone, otherwise they are * properly filled. The version parameter uses the values for the MIB variable* stored in ripState.ripConf.rip2IfConfSend instead of the actual version* number. This routine is never called if that value is set to disable* transmission.** RETURNS: N/A** NOMANUAL*/void ripBuildPacket ( RIP2PKT *pPacket, struct rt_entry* rt, struct interface * pIf, int version ) { UINT32 routenet = 0; /* Network number of route gateway */ UINT32 destnet = 0; /* Network number of route destination */ struct sockaddr_in* dSin; struct sockaddr_in* gSin; struct sockaddr_in* nSin; if (version == M2_rip2IfConfSend_ripVersion1) { pPacket->tag = 0; ripRouteToAddrs(rt, &dSin, &gSin, &nSin); pPacket->dest = dSin->sin_addr.s_addr; pPacket->subnet = 0; pPacket->gateway = 0; pPacket->metric = htonl(rt->rt_metric); } else { /* * Building version 2 packets requires special processing to * support both RIP-1 and RIP-2 routers in all situations. */ pPacket->tag = 0; ripRouteToAddrs(rt, &dSin, &gSin, &nSin); if (nSin->sin_addr.s_addr) { /* * Don't apply the route's netmask if it is shorter than the * mask of the outgoing interface. The interface's mask is used * for those destinations so that an unreachable gateway is not * sent. The shorter mask could conceal the network mismatch, * (e.g. - 147.11.151.47/23 and 147.11.150.48/24 would match * in that case). */ if ( (nSin->sin_addr.s_addr & htonl (pIf->int_subnetmask)) == pIf->int_subnetmask) routenet = gSin->sin_addr.s_addr & nSin->sin_addr.s_addr; else routenet = gSin->sin_addr.s_addr & pIf->int_subnetmask; } else routenet = gSin->sin_addr.s_addr & pIf->int_subnetmask; destnet = (*(UINT32 *)(&pIf->int_addr.sa_data[0] + 2) & pIf->int_subnetmask); /* No special processing is required for the advertised destination. */ pPacket->dest = dSin->sin_addr.s_addr; /* * Internally generated entries which substitute for supernets * still contain the classless netmask so that the border gateway * filtering can select the correct entry for both directly connected * and "distant" destinations. That value must be replaced with * the "natural" (class-based) network mask before the update is * sent so that the route will be understood by RIP-2 routers. If * border gateway filtering was disabled, none of the internally * generated entries will be included in any update, so this * substitution is (correctly) ignored. */ if ( (rt->rt_state & (RTS_INTERNAL | RTS_SUBNET)) == (RTS_INTERNAL | RTS_SUBNET)) { /* * For internal routes, the route entry's netmask is equal to * rt->rt_ifp->int_netmask unless it is a substitute for a * supernet. */ if (ntohl (nSin->sin_addr.s_addr) != rt->rt_ifp->int_netmask) { /* * Substitute the class-based value for the * supernet mask in the outgoing message. */ pPacket->subnet = htonl (rt->rt_ifp->int_netmask); } else { /* * For subnet replacements, use the existing * (class-based) value. */ pPacket->subnet = nSin->sin_addr.s_addr; } } else { /* * Common case: use mask from actual route entry. This * case includes the internally generated default route * created when the gateway flag is set during initialization. */ pPacket->subnet = nSin->sin_addr.s_addr; } /* * For RIPv2 packets, the network number of the published gateway * must match the network number of the outgoing interface. Unless * the host contains multiple interfaces with the same network * number, the value stored in the RIP routing table generally * contains an address on a different network. In that case, * use the interface IP address to include a reachable gateway in * the route update. */ if (routenet != destnet) pPacket->gateway = *(UINT32 *)(&pIf->int_addr.sa_data[0] + 2); else pPacket->gateway = gSin->sin_addr.s_addr; /* * Unlike the gateway and netmask, the specified metric * can always be copied directly. */ pPacket->metric = htonl(rt->rt_metric); } }/******************************************************************************** ripRouteShow - display the internal routing table maintained by RIP** This routine prints every entry in the local RIP routing table. The* flags displayed below the destination, gateway, and netmask addresses* indicate the current route status. Entries with the RTS_INTERFACE flag* indicate routes to directly connected networks which are generated * locally. If RTS_SUBNET is set for an entry, it is subject to border* gateway filtering (if enabled). When RTS_INTERNAL is also present, the * corresponding entry is an "artificial" route created to supply distant* networks with legitimate destinations if border filtering excludes the* actual entry. Those entries are not copied to the kernel routing table.* The RTS_CHANGED flag marks entries added or modified in the last timer * interval which will be included in a triggered update.** RETURNS: N/A** ERRNO: N/A*/void ripRouteShow() { int doinghost = 1; register struct rthash *rh; register struct rt_entry *rt; struct rthash *base = hosthash; struct sockaddr_in* dSin; struct sockaddr_in* gSin; struct sockaddr_in* nSin; char address[32]; if (!ripInitFlag) return; /* Block all processing to guarantee a stable list of routes. */ semTake (ripLockSem, WAIT_FOREVER); again: for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) { rt = rh->rt_forw; for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { ripRouteToAddrs(rt, &dSin, &gSin, &nSin); inet_ntoa_b(dSin->sin_addr, (char *)&address); printf("%s\t", address); inet_ntoa_b(gSin->sin_addr, (char *)&address); printf("%s\t", address); inet_ntoa_b(nSin->sin_addr, (char *)&address); printf("%s\t", address); printf("Metric: %d\t", rt->rt_metric); printf("Timer: %d\n", rt->rt_timer); /* Now figure out all the state. */ if (rt->rt_state & RTS_CHANGED) printf("RTS_CHANGED "); if (rt->rt_state & RTS_EXTERNAL) printf("RTS_EXTERNAL "); if (rt->rt_state & RTS_INTERNAL) printf("RTS_INTERNAL "); if (rt->rt_state & RTS_PASSIVE) printf("RTS_PASSIVE "); if (rt->rt_state & RTS_INTERFACE) printf("RTS_INTERFACE "); if (rt->rt_state & RTS_REMOTE) printf("RTS_REMOTE "); if (rt->rt_state & RTS_SUBNET) printf("RTS_SUBNET "); printf ("\n"); } } if (doinghost) { doinghost = 0; base = nethash; goto again; } semGive (ripLockSem); return; }/******************************************************************************* ripSetInterfaces - add all multicast interfaces to address group** This routine sets all interfaces that are multicast capable into the* multicast group address passed in as an argument.** RETURNS: N/A** NOMANUAL*/void ripSetInterfaces ( INT32 sock, UINT32 mcastAddr /* Address to join. */ ) { struct ip_mreq ipMreq; /* Multicast structure for version 2 */ struct ifreq ifbuf[32]; struct ifreq *ifrp; struct ifreq *ifend; struct ifconf ifc; int n = 0; UINT32 addr; ifc.ifc_buf = (char *)ifbuf; ifc.ifc_len = sizeof(ifbuf); if (ioctl(sock, SIOCGIFCONF, (UINT32)(char *)&ifc) < 0) if (routedDebug) logMsg ("SIOCGIFCONF error adding multicast address", 0, 0, 0, 0, 0, 0); ifrp = (struct ifreq *)ifbuf; ifend = (struct ifreq *)((char *)ifbuf + ifc.ifc_len); /* * Loop through all of the interfaces. */ for (; ifrp < ifend; ifrp = (struct ifreq *)((char *)ifrp + n)) { n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name); if (n < sizeof(*ifrp)) n = sizeof(*ifrp); /* * Ignore any interface for an address family other than IP. */ if (ifrp->ifr_addr.sa_family != AF_INET) continue; addr = ((struct sockaddr_in *)&ifrp->ifr_addr)->sin_addr.s_addr; ipMreq.imr_multiaddr.s_addr = htonl (mcastAddr); ipMreq.imr_interface.s_addr = addr; if (setsockopt (sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&ipMreq, sizeof (ipMreq)) < 0) { if (routedDebug) logMsg ("setsockopt IP_ADD_MEMBERSHIP error:\n", 0, 0, 0, 0, 0, 0); } } }/******************************************************************************* ripClearInterfaces - remove all multicast interfaces from address group** This routine removes all interfaces that are multicast capable from the* multicast group address given by <mcastAddr>. It is called when changing* the receive control switch from RIP-2 only mode with SNMP. Although it * seems acceptable to allow membership in the multicast group unless the * receive switch is set to RIP-1 only mode, ANVL test 16.1 would fail.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -