ripLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:173k
- printf (" %sn", rt->rt_ifp->int_name);
- /* 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 ");
- if (rt->rt_state & RTS_OTHER)
- {
- printf ("RTS_OTHER ");
- if (rt->rt_state & RTS_PRIMARY)
- printf ("RTS_PRIMARY ");
- }
- if (rt->rt_ifp && (rt->rt_ifp->int_flags & IFF_UP) == 0)
- printf ("DOWN ");
- printf ("n");
- }
- }
- if (doinghost)
- {
- printf ("-----------------------------------------------------------------n");
- doinghost = 0;
- base = nethash;
- goto again;
- }
- 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 interface * pIf;
- UINT32 addr;
- for (pIf = ripIfNet; pIf; pIf = pIf->int_next)
- {
- addr = ((struct sockaddr_in *)&(pIf->int_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.
- *
- * RETURNS: N/A
- *
- * NOMANUAL
- */
- void ripClearInterfaces
- (
- INT32 sock,
- UINT32 mcastAddr /* Address to join. */
- )
- {
- struct ip_mreq ipMreq; /* Multicast structure for version 2 */
- struct interface * pIf;
- UINT32 addr;
- for (pIf = ripIfNet; pIf; pIf = pIf->int_next)
- {
- addr = ((struct sockaddr_in *)&(pIf->int_addr))->sin_addr.s_addr;
- ipMreq.imr_multiaddr.s_addr = htonl (mcastAddr);
- ipMreq.imr_interface.s_addr = addr;
- if (setsockopt (sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,
- (char *)&ipMreq, sizeof (ipMreq)) < 0)
- {
- if (routedDebug)
- logMsg ("setsockopt IP_DROP_MEMBERSHIP error.n",
- 0, 0, 0, 0, 0, 0);
- }
- }
- }
- /******************************************************************************
- *
- * _ripIfShow - display information about an interface
- *
- * This routine prints information about an interface entry.
- * The interface name, interface index, the UP/DOWN status and the
- * interface address and netmask are displayed.
- *
- * RETURNS: N/A
- *
- * ERRNO: N/A
- *
- * NOMANUAL
- */
- void _ripIfShow
- (
- struct interface * pIf
- )
- {
- char address[32];
- struct in_addr sin_addr;
- printf ("%-8s%-8d%-12s",
- pIf->int_name, pIf->int_index,
- (pIf->int_flags & IFF_UP) == IFF_UP ? "UP" : "DOWN");
- inet_ntoa_b (((struct sockaddr_in *)&(pIf->int_addr))->sin_addr,
- address);
- printf ("%-17s", address);
- sin_addr.s_addr = htonl (pIf->int_subnetmask);
- inet_ntoa_b (sin_addr, address);
- printf ("%-17s", address);
- inet_ntoa_b (((struct sockaddr_in *)&(pIf->int_broadaddr))->sin_addr,
- address);
- printf ("%-17sn", address);
- return;
- }
- /******************************************************************************
- *
- * ripIfShow - display the internal interface table maintained by RIP
- *
- * This routine prints every entry in the local RIP interface table.
- * The interface name, interface index, the UP/DOWN status and the
- * interface address and netmask are displayed.
- *
- * RETURNS: N/A
- *
- * ERRNO: N/A
- */
- void ripIfShow (void)
- {
- struct interface * pIf;
- if (!ripInitFlag)
- return;
- /* Block all processing to guarantee a stable list of interfaces. */
- semTake (ripLockSem, WAIT_FOREVER);
-
- /*
- * Loop through the interface list printing out the
- * interface name index UP/DOWN status I/f addr I/f netmask
- */
- printf ("Name Index Up/Down Address Netmask "
- "Broadcastn");
- for (pIf = ripIfNet; pIf; pIf = pIf->int_next)
- _ripIfShow (pIf);
-
- semGive (ripLockSem);
- return;
- }
- /******************************************************************************
- *
- * ripAuthHookAdd - add an authentication hook to a RIP interface
- *
- * This routine installs a hook routine to validate incoming RIP messages
- * for a registered interface given by <pIpAddr>. (Interfaces created or
- * changed after a RIP session has started may be installed/updated with the
- * ripIfSearch() and ripIfReset() routines). The hook is only called if
- * an SNMP agent enables authentication for the corresponding interface.
- * It uses the following prototype:
- *
- * cs
- * STATUS ripAuthHookRtn (char *pKey, RIP_PKT *pRip);
- * ce
- * The first argument contains the authentication key for the message
- * stored in the rip2IfConfAuthKey MIB variable and the second argument
- * uses the RIP_PKT structure (defined in rip/ripLib.h) to access the message
- * body. The routine must return OK if the message is acceptable, or ERROR
- * otherwise. All RIP-2 messages sent to that routine already contain an
- * authentication entry, but have not been verified. (Any unauthenticated
- * RIP-2 messages have already been discarded as required by the RFC
- * specification). RIP-1 messages may be accepted or rejected. RIP-2 messages
- * requesting simple password authentication that match the key are
- * accepted automatically before the hook is called. The remaining RIP-2
- * messages either did not match that key or are using an unknown
- * authentication type. If any messages are rejected, the MIB-II counters are
- * updated appropriately outside of the hook routine.
- *
- * The current RIP implementation contains a sample authentication hook that
- * you may add as follows:
- *
- * cs
- * if (ripAuthHookAdd ("90.0.0.1", ripAuthHook) == ERROR)
- * logMsg ("Unable to add authorization hook.n", 0, 0, 0, 0, 0, 0);
- * ce
- *
- * The sample routine supports only simple password authentication against
- * the key included in the MIB variable. Since all such messages have already
- * been accepted, all RIP-2 messages received by the routine are discarded.
- * All RIP-1 messages are also discarded, so the hook actually has no
- * effect. The body of that routine is:
- *
- * cs
- * STATUS ripAuthHook
- * (
- * char * pKey, /@ rip2IfConfAuthKey entry from MIB-II family @/
- * RIP_PKT * pRip /@ received RIP message @/
- * )
- * {
- * if (pRip->rip_vers == 1)
- * {
- * /@
- * @ The RFC specification recommends, but does not require, rejecting
- * @ version 1 packets when authentication is enabled.
- * @/
- *
- * return (ERROR);
- * }
- *
- * /@
- * @ The authentication type field in the RIP message corresponds to
- * @ the first two bytes of the sa_data field overlayed on that
- * @ message by the sockaddr structure contained within the RIP_PKT
- * @ structure (see rip/ripLib.h).
- * @/
- *
- * if ( (pRip->rip_nets[0].rip_dst.sa_data[0] != 0) ||
- * (pRip->rip_nets[0].rip_dst.sa_data[1] !=
- * M2_rip2IfConfAuthType_simplePassword))
- * {
- * /@ Unrecognized authentication type. @/
- *
- * return (ERROR);
- * }
- *
- * /@
- * @ Discard version 2 packets requesting simple password authentication
- * @ which did not match the MIB variable.
- * @/
- *
- * return (ERROR);
- * }
- * ce
- *
- * A comparison against a different key could be performed as follows:
- *
- * cs
- * bzero ( (char *)&key, AUTHKEYLEN); /@ AUTHKEYLEN from rip/m2RipLib.h @/
- *
- * /@
- * @ The start of the authorization key corresponds to the third byte
- * @ of the sa_data field in the sockaddr structure overlayed on the
- * @ body of the RIP message by the RIP_PKT structure. It continues
- * @ for the final 14 bytes of that structure and the first two bytes
- * @ of the following rip_metric field.
- * @/
- *
- * bcopy ( (char *)(pRip->rip_nets[0].rip_dst.sa_data + 2),
- * (char *)&key, AUTHKEYLEN);
- *
- * if (bcmp ( (char *)key, privateKey, AUTHKEYLEN) != 0)
- * {
- * /@ Key does not match: reject message. @/
- *
- * return (ERROR);
- * }
- * return (OK);
- * ce
- *
- * The ripAuthHookDelete() routine will remove the installed function. If
- * authentication is still enabled for the interface, all incoming messages
- * that do not use simple password authentication will be rejected until a
- * routine is provided.
- *
- * RETURNS: OK, if hook added; or ERROR otherwise.
- *
- * ERRNO:
- * S_m2Lib_INVALID_PARAMETER
- * S_m2Lib_ENTRY_NOT_FOUND
- */
- STATUS ripAuthHookAdd
- (
- char* pIpAddr, /* IP address in dotted decimal notation */
- FUNCPTR pAuthHook /* routine to handle message authentication */
- )
- {
- struct interface* pIfp;
- struct sockaddr_in address;
- if (!ripInitFlag)
- return (ERROR);
- if (pIpAddr == NULL)
- {
- errnoSet (S_m2Lib_INVALID_PARAMETER);
- return (ERROR);
- }
- address.sin_len = sizeof (address);
- address.sin_addr.s_addr = inet_addr (pIpAddr);
- address.sin_family = AF_INET;
-
- pIfp = ripIfLookup ((struct sockaddr *)&address);
- if (pIfp == NULL)
- {
- errnoSet (S_m2Lib_ENTRY_NOT_FOUND);
- return (ERROR);
- }
- /* Short critical section with input processing. */
- semTake (ripLockSem, WAIT_FOREVER);
- pIfp->authHook = pAuthHook;
- semGive (ripLockSem);
-
- return (OK);
- }
- /******************************************************************************
- *
- * ripAuthHookDelete - remove an authentication hook from a RIP interface
- *
- * This routine removes an assigned authentication hook from a registered
- * interface indicated by <pIpAddr>. (Interfaces created or changed after
- * a RIP session has started may be installed/updated with the ripIfSearch()
- * and ripIfReset() routines). If authentication is still enabled for the
- * interface, RIP-2 messages using simple password authentication will be
- * accepted if they match the key in the MIB variable, but all other incoming
- * messages will be rejected until a routine is provided.
- *
- * RETURNS: OK; or ERROR, if the interface could not be found.
- *
- * ERRNO:
- * S_m2Lib_INVALID_PARAMETER
- * S_m2Lib_ENTRY_NOT_FOUND
- */
- STATUS ripAuthHookDelete
- (
- char* pIpAddr /* IP address in dotted decimal notation */
- )
- {
- struct interface* pIfp;
- struct sockaddr_in address;
- if (!ripInitFlag)
- return (ERROR);
- if (pIpAddr == NULL)
- {
- errnoSet (S_m2Lib_INVALID_PARAMETER);
- return (ERROR);
- }
- address.sin_len = sizeof (address);
- address.sin_addr.s_addr = inet_addr (pIpAddr);
- address.sin_family = AF_INET;
-
- pIfp = ripIfLookup ( (struct sockaddr *)&address);
- if (pIfp == NULL)
- {
- errnoSet (S_m2Lib_ENTRY_NOT_FOUND);
- return (ERROR);
- }
- /* Short critical section with input processing. */
-
- semTake (ripLockSem, WAIT_FOREVER);
- pIfp->authHook = NULL;
- semGive (ripLockSem);
-
- return (OK);
- }
- /******************************************************************************
- *
- * ripAuthCheck - verify RIP messages if authentication is enabled
- *
- * This routine accepts all RIP-2 messages using simple password
- * authentication that match the key in the MIB variable. It is
- * called automatically when authentication is enabled. All other
- * RIP-2 messages and any RIP-1 messages may be accepted by an
- * authentication hook, or will be discarded if no hook is present.
- *
- * RETURNS: OK, if message is acceptable; or ERROR otherwise.
- *
- * NOMANUAL
- */
- STATUS ripAuthCheck
- (
- char * pKey, /* rip2IfConfAuthKey entry from MIB-II family */
- RIP_PKT * pRip /* received RIP message */
- )
- {
- if (pRip->rip_vers == 1)
- {
- /*
- * The RFC specification recommends, but does not require, rejecting
- * version 1 packets when authentication is enabled. Those packets
- * will be discarded unless accepted by the hook.
- */
- return (ERROR);
- }
- /*
- * The authentication type field in the RIP message corresponds to
- * the first two bytes of the sa_data field overlayed on that
- * message by the sockaddr structure contained within the RIP_PKT
- * structure (see rip/ripLib.h).
- */
- if ((pRip->rip_nets[0].rip_dst.sa_data[0] != 0) ||
- (pRip->rip_nets[0].rip_dst.sa_data[1] !=
- M2_rip2IfConfAuthType_simplePassword))
- {
- /*
- * Reject messages with an unrecognized authentication type. This
- * behavior can be overridden by the user's authentication hook.
- */
- return (ERROR);
- }
- /*
- * The start of the authorization key corresponds to the third byte
- * of the sa_data field in the sockaddr structure and continues for
- * AUTHKEYLEN bytes (defined in rip/m2RipLib.h).
- */
- if (bcmp ( (char *)(pRip->rip_nets[0].rip_dst.sa_data + 2),
- pKey, AUTHKEYLEN) != 0)
- {
- return (ERROR);
- }
- /*
- * Accept version 2 packets requesting simple password
- * authentication that matched the MIB variable.
- */
- return (OK);
- }
- /******************************************************************************
- *
- * ripAuthHook - sample authentication hook
- *
- * This hook demonstrates one possible authentication mechanism. It rejects
- * all RIP-2 messages that used simple password authentication since they
- * did not match the key contained in the MIB variable. All other RIP-2
- * messages are also rejected since no other authentication type is
- * supported and all RIP-1 messages are also rejected, as recommended by
- * the RFC specification. This behavior is the same as if no hook were
- * installed.
- *
- * RETURNS: OK, if message is acceptable; or ERROR otherwise.
- */
- STATUS ripAuthHook
- (
- char * pKey, /* rip2IfConfAuthKey entry from MIB-II family */
- RIP_PKT * pRip /* received RIP message */
- )
- {
- if (pRip->rip_vers == 1)
- {
- /*
- * The RFC specification recommends, but does not require, rejecting
- * version 1 packets when authentication is enabled.
- */
- return (ERROR);
- }
- /*
- * The authentication type field in the RIP message corresponds to
- * the first two bytes of the sa_data field overlayed on that
- * message by the sockaddr structure contained within the RIP_PKT
- * structure (see rip/ripLib.h).
- */
- if ((pRip->rip_nets[0].rip_dst.sa_data[0] != 0) ||
- (pRip->rip_nets[0].rip_dst.sa_data[1] !=
- M2_rip2IfConfAuthType_simplePassword))
- {
- /* Unrecognized authentication type. */
- return (ERROR);
- }
- /*
- * Discard version 2 packets requesting simple password
- * authentication that did not match the MIB variable.
- */
- return (ERROR);
- }
- /******************************************************************************
- *
- * ripLeakHookAdd - add a hook to bypass the RIP and kernel routing tables
- *
- * This routine installs a hook routine to support alternative routing
- * protocols for the registered interface given by <pIpAddr>. (Interfaces
- * created or changed after a RIP session has started may be installed/updated
- * with the ripIfSearch() and ripIfReset() routines).
- *
- * The hook uses the following interface:
- * cs
- * STATUS ripLeakHookRtn (long dest, long gateway, long netmask)
- * ce
- *
- * The RIP session will not add the given route to any tables if the hook
- * routine returns OK, but will create a route entry otherwise.
- *
- * The ripLeakHookDelete() will allow the RIP session to add new routes
- * unconditionally.
- *
- * RETURNS: OK; or ERROR, if the interface could not be found.
- *
- * ERRNO:
- * S_m2Lib_INVALID_PARAMETER
- * S_m2Lib_ENTRY_NOT_FOUND
- */
- STATUS ripLeakHookAdd
- (
- char * pIpAddr, /* IP address in dotted decimal notation */
- FUNCPTR pLeakHook /* function pointer to hook */
- )
- {
- struct interface* pIfp;
- struct sockaddr_in address;
- if (!ripInitFlag)
- return (ERROR);
- if (pIpAddr == NULL)
- {
- errnoSet (S_m2Lib_INVALID_PARAMETER);
- return (ERROR);
- }
- address.sin_len = sizeof (address);
- address.sin_addr.s_addr = inet_addr (pIpAddr);
- address.sin_family = AF_INET;
-
- pIfp = ripIfLookup ((struct sockaddr *)&address);
- if (pIfp == NULL)
- {
- errnoSet (S_m2Lib_ENTRY_NOT_FOUND);
- return (ERROR);
- }
- /* Short critical section with message and timer processing. */
-
- semTake (ripLockSem, WAIT_FOREVER);
- pIfp->leakHook = pLeakHook;
- semGive (ripLockSem);
- return (OK);
- }
- /******************************************************************************
- *
- * ripLeakHookDelete - remove a table bypass hook from a RIP interface
- *
- * This routine removes the assigned bypass hook from a registered interface
- * indicated by <pIpAddr>. (Interfaces created or changed after a RIP
- * session has started may be installed/updated with the ripIfSearch()
- * and ripIfReset() routines). The RIP session will return to the default
- * behavior and add entries to the internal RIP table and kernel routing
- * table unconditionally.
- *
- * RETURNS: OK; or ERROR, if the interface could not be found.
- *
- * ERRNO:
- * S_m2Lib_INVALID_PARAMETER
- * S_m2Lib_ENTRY_NOT_FOUND
- */
- STATUS ripLeakHookDelete
- (
- char* pIpAddr /* IP address in dotted decimal notation */
- )
- {
- struct interface* pIfp;
- struct sockaddr_in address;
- if (!ripInitFlag)
- return (ERROR);
- if (pIpAddr == NULL)
- {
- errnoSet (S_m2Lib_INVALID_PARAMETER);
- return (ERROR);
- }
- address.sin_len = sizeof (address);
- address.sin_addr.s_addr = inet_addr (pIpAddr);
- address.sin_family = AF_INET;
-
- pIfp = ripIfLookup ((struct sockaddr *)&address);
- if (pIfp == NULL)
- {
- errnoSet (S_m2Lib_ENTRY_NOT_FOUND);
- return (ERROR);
- }
-
- /* Short critical section with message and timer processing. */
-
- semTake (ripLockSem, WAIT_FOREVER);
- pIfp->leakHook = NULL;
- semGive (ripLockSem);
-
- return (OK);
- }
- /******************************************************************************
- *
- * ripLeakHook - sample leak hook for RIP routes
- *
- * This routine prevents any routes from being added to the internal RIP
- * table or kernel routing table, and prints the information that was passed
- * to it.
- *
- * RETURNS: OK
- *
- * NOMANUAL
- */
- STATUS ripLeakHook
- (
- long dest,
- long gate,
- long mask
- )
- {
- printf ("Destination %lxtGateway %lxtMask %lxn", dest, gate, mask);
- return (OK);
- }
- /******************************************************************************
- *
- * ripSendHookAdd - add an update filter to a RIP interface
- *
- * This routine installs a hook routine to screen individual route entries
- * for inclusion in a periodic update. The routine is installed for the
- * registered interface given by <pIpAddr>. (Interfaces created or
- * changed after a RIP session has started may be installed/updated with
- * the ripIfSearch() and ripIfReset() routines).
- *
- * The hook uses the following prototype:
- * cs
- * BOOL ripSendHookRtn (struct rt_entry* pRt);
- * ce
- *
- * If the hook returns FALSE, the route is not included in the update.
- * Otherwise, it is included if it meets the other restrictions, such
- * as simple split horizon and border gateway filtering. The
- * ripSendHookDelete() routine removes this additional filter from the
- * output processing.
- *
- * RETURNS: OK; or ERROR, if the interface could not be found.
- *
- * ERRNO:
- * S_m2Lib_INVALID_PARAMETER
- * S_m2Lib_ENTRY_NOT_FOUND
- */
- STATUS ripSendHookAdd
- (
- char* pIpAddr, /* IP address in dotted decimal notation */
- BOOL (*ripSendHook) (struct rt_entry* pRt) /* Routine to use. */
- )
- {
- struct interface* pIfp;
- struct sockaddr_in address;
- if (!ripInitFlag)
- return (ERROR);
- if (pIpAddr == NULL)
- {
- errnoSet (S_m2Lib_INVALID_PARAMETER);
- return (ERROR);
- }
- address.sin_len = sizeof (address);
- address.sin_addr.s_addr = inet_addr (pIpAddr);
- address.sin_family = AF_INET;
-
- pIfp = ripIfLookup ((struct sockaddr *)&address);
- if (pIfp == NULL)
- {
- errnoSet (S_m2Lib_ENTRY_NOT_FOUND);
- return (ERROR);
- }
- /* Short critical section with output processing. */
-
- semTake (ripLockSem, WAIT_FOREVER);
- pIfp->sendHook = ripSendHook;
- semGive (ripLockSem);
-
- return (OK);
- }
- /******************************************************************************
- *
- * ripSendHookDelete - remove an update filter from a RIP interface
- *
- * This routine removes the hook routine that allowed additional screening
- * of route entries in periodic updates from the registered interface
- * indicated by <pIpAddr>. (Interfaces created or changed after a RIP
- * session has started may be installed/updated with the ripIfSearch()
- * and ripIfReset() routines). The RIP session will return to the default
- * behavior and include any entries that meet the other restrictions (such
- * as simple split horizon).
- *
- * RETURNS: OK; or ERROR, if the interface could not be found.
- *
- * ERRNO:
- * S_m2Lib_INVALID_PARAMETER
- * S_m2Lib_ENTRY_NOT_FOUND
- */
- STATUS ripSendHookDelete
- (
- char* pIpAddr /* IP address in dotted decimal notation */
- )
- {
- struct interface* pIfp;
- struct sockaddr_in address;
- if (!ripInitFlag)
- return (ERROR);
- if (pIpAddr == NULL)
- {
- errnoSet (S_m2Lib_INVALID_PARAMETER);
- return (ERROR);
- }
- address.sin_len = sizeof (address);
- address.sin_addr.s_addr = inet_addr (pIpAddr);
- address.sin_family = AF_INET;
-
- pIfp = ripIfLookup ((struct sockaddr *)&address);
- if (pIfp == NULL)
- {
- errnoSet (S_m2Lib_ENTRY_NOT_FOUND);
- return (ERROR);
- }
- /* Short critical section with output processing. */
- semTake (ripLockSem, WAIT_FOREVER);
- pIfp->sendHook = NULL;
- semGive (ripLockSem);
-
- return (OK);
- }
- /******************************************************************************
- *
- * ripSendHook - sample send hook for rip routes
- *
- * This routine displays all the routes that are being sent and returns OK
- * so that they are included in the update if all other criteria are met.
- *
- * RETURNS: OK
- *
- * NOMANUAL
- */
- BOOL ripSendHook
- (
- struct rt_entry* pRt
- )
- {
- char address[32];
- struct sockaddr_in* dSin;
- struct sockaddr_in* gSin;
- struct sockaddr_in* nSin;
- ripRouteToAddrs (pRt, &dSin, &gSin, &nSin);
- inet_ntoa_b (dSin->sin_addr, (char *)&address);
- printf ("Route to %s ", address);
- inet_ntoa_b (gSin->sin_addr, (char *)&address);
- printf ("with gateway %s ", address);
- inet_ntoa_b (nSin->sin_addr, (char *)&address);
- printf ("and netmask %s being sent.n", address);
- return (OK);
- }
- /******************************************************************************
- *
- * ripRouteHookAdd - add a hook to install static and non-RIP routes into RIP
- *
- * This routine installs a hook routine that you can use to give RIP the
- * ability to respond to route-add events generated by non-RIP agents. By
- * design, RIP is not interested in the routes generated by non-RIP agents.
- * If you do not install a route hook function, RIP continues this default
- * behavior. However, if you want RIP to add these non-RIP routes to its
- * internal routing database and even propagate routes added by other
- * agents, you must use ripRouteHookAdd() to register a function of the form:
- *
- * ss
- * STATUS <Your>RipRouteHookRtn
- * (
- * struct ROUTE_INFO * pRouteInfo,
- * int protoId,
- * BOOL primaryRoute,
- * int flags
- * )
- * se
- * RIP invokes this function in response to the following events:
- *
- * '1.' A non-RIP non-system route was added to the routing table.
- * '2.' A route change message arrived.
- * '3.' An ICMP redirect message arrived.
- *
- * The returned function value of the route hook routine tells rip
- * how to respond to the event. In the first case, the returned
- * function value tells RIP whether to add or ignore the new route.
- * In the second case, the returned function tells RIP whether to
- * delete the specified route or change its metric. In the third
- * case, the event is of no direct importance for RIP, so RIP
- * ignores the returned value of the route hook function.
- * is
- * i <pRouteInfo>
- * This parameter passes in a pointer to a route information
- * structure that stores the routing message. You should not
- * access the contents of this structure directly. Instead,
- * use ripAddrsXtract() to extract the following information:
- *
- * '-' destination address
- * '-' netmask
- * '-' gateway address
- * '-' old gateway address (if available)
- *
- * i <protoId>
- * This parameter passes in the ID of the protocol that generated
- * the event. Valid protocol IDs are defined in m2Lib.h as follows:
- *
- * 'M2_ipRouteProto_other' (static routes)
- * 'M2_ipRouteProto_local'
- * 'M2_ipRouteProto_netmgmt'
- * 'M2_ipRouteProto_icmp'
- * 'M2_ipRouteProto_egp'
- * 'M2_ipRouteProto_ggp'
- * 'M2_ipRouteProto_hello'
- * 'M2_ipRouteProto_rip'
- * 'M2_ipRouteProto_is_is'
- * 'M2_ipRouteProto_es_is'
- * 'M2_ipRouteProto_ciscoIgrp'
- * 'M2_ipRouteProto_bbnSpfIgp'
- * 'M2_ipRouteProto_ospf'
- * 'M2_ipRouteProto_bgp'
- *
- * i <primaryRoute>
- * This parameter passes in a boolean value that indicates whether
- * the route is a primary route. 'TRUE' indicates a primary route.
- * 'FALSE' indicates a duplicate route.
- * i <flags>
- * This parameter passes in a value that indicates which event occurred:
- *
- * '0' (zero)
- * This indicates a route added to the routing table by a non-RIP agent.
- *
- * 'RIP_ROUTE_CHANGE_RECD'
- * This indicates a route change message.
- *
- * 'RIP_REDIRECT_RECD'
- * This indicates and ICMP redirect message.
- * ie
- * sh A New Non-RIP Non-System Route was Added to the Routing Table
- *
- * In response to this event, RIP needs to be told whether to ignore
- * or add the route. RIP does this on the basis of the returned
- * function value of the route hook routine. In the case of route-add
- * event, RIP interprets the returned function value of the route hook
- * routine as the metric for the route.
- *
- * If the metric is HOPCNT_INFINITY, RIP ignores the route. If the
- * metric is greater than zero but less than HOPCNT_INFINITY, RIP
- * considers the route for inclusion. If the route is new to RIP, RIP
- * adds the new route to its internal database, and then propagates
- * the route in its subsequent update messages. If RIP already stores
- * a route for that destination, RIP compares the metric of the new
- * route and the stored route. If the new route has a better (lower)
- * metric, RIP adds the new route. Otherwise, RIP ignores the new route.
- *
- * When generating its returned function value, your route hook
- * routine can use the creator of the event (<protoID>) as a factor
- * in the decision on whether to include the route. For example,
- * if you wanted the route hook to tell RIP to ignore all non-RIP
- * routes except static routes, your route hook would return
- * HOPCNT_INFINITY if the <protoID> were anything other than
- * 'M2_ipRouteProto_other'. Thus, your route hook routine is a
- * vehicle through which you can implement a policy for including
- * non-RIP routes in the RIP internal route data base.
- *
- * When designing your policy, you should keep in mind how RIP
- * prioritizes these non-RIP routes and when it deletes these
- * non-RIP routes. For example, non-RIP routes never time out.
- * They remain in the RIP database until one of the following
- * events occurs:
- *
- * '1.' An agent deletes the route from the system routing table.
- * '2.' An agent deletes the interface through which the route passes.
- * '3.' A route change message for the route arrives.
- *
- * Also, these non-RIP routes take precedence over RIP routes to
- * the same destination. RIP ignores routes learned from RIP peers
- * if a route to the same destination was recommended by the hook
- * routine. This non-RIP route takes precedence over the RIP route
- * without regard of the route metric. However, if the route hook
- * routine adds multiple same-destination routes, the route with
- * the lowest metric takes precedence. If the route hook route
- * approves multiple same-metric same-destination routes, the
- * most recently added route is installed.
- *
- * sh A Route Change Notification Arrived
- *
- * In response to this event, RIP needs to be told whether to
- * delete the route or change its metric. If the hook returns a
- * value greater than or equal to HOPCNT_INFINITY, RIP deletes
- * the route from its internal routing data base. If the hook
- * routine returns a valid metric (a value greater than zero
- * but less than HOPCNT_INFINITY), RIP reassigns the routes
- * metric to equal the returned value of the route hook routine.
- * If the returned value of the route hook route is invalid
- * (less than zero) RIP ignores the event. RIP also ignores
- * the event if the route specified in <pRouteInfo> is not one
- * stored in its internal data base.
- *
- * sh An ICMP Redirect Message Arrived
- *
- * In response to this event, RIP never needs to make any changes
- * to its internal routing database. Thus, RIP ignores the returned
- * function value of the route hook routine called in response
- * to an ICMP redirect message. However, if the event is of
- * interest to your particular environment, and it makes sense
- * to catch the event in the context of the RIP task, you can
- * use the route hook routine to do so.
- *
- * Within your route hook routine, your can recognize an ICMP
- * event by checking whether the flags parameter value sets
- * the RIP_REDIRECT_RECD bit. The <primaryRoute> parameter passes
- * in a boolean value that indicates whether the route is
- * primary route. If the <primaryRoute> passes in 'FALSE', the
- * route hook routine need will most likely need to do nothing
- * more. If this parameter passes in 'TRUE', take whatever action
- * (if any) that you know to be appropriate to your particular
- * environment.
- *
- * RETURNS: OK; or ERROR, if RIP is not initialized.
- */
- STATUS ripRouteHookAdd
- (
- FUNCPTR pRouteHook /* function pointer to hook */
- )
- {
- if (!ripInitFlag)
- return (ERROR);
- /* Short critical section with message and timer processing. */
-
- semTake (ripLockSem, WAIT_FOREVER);
- ripState.pRouteHook = pRouteHook;
- semGive (ripLockSem);
- return (OK);
- }
- /****************************************************************************
- *
- * ripRouteHookDelete - remove the route hook
- *
- * This routine removes the route hook installed earlier by the
- * ripRouteHookAdd() routine. This will cause RIP to ignore any routes
- * added to the system Routing database.
- *
- * RETURNS: OK; or ERROR, if RIP is not initialized.
- *
- */
- STATUS ripRouteHookDelete (void)
- {
- if (!ripInitFlag)
- return (ERROR);
-
- /* Short critical section with message and timer processing. */
-
- semTake (ripLockSem, WAIT_FOREVER);
- ripState.pRouteHook = NULL;
- semGive (ripLockSem);
-
- return (OK);
- }
- /****************************************************************************
- *
- * ripRouteHook - sample route hook for non-RIP and redirected routes
- *
- * This routine allows RIP to include static (and other protocol) routes in
- * its database and propagate them to its peers.
- * <pRouteInfo> points to a routing socket message structure that describes
- * the route details.
- * <protoId> identifies that routing protocol that is installing this route.
- * <primaryRoute> indicate if this is the route that will be used by the
- * IP forwarding process.
- * <flags> denote if this is a ICMP redirected route or a changed route or
- * a new route.
- * flags == 0 New route (non-RIP)
- * flags == RIP_REDIRECT_RECD ICMP redirected route
- * flags == RIP_ROUTE_CHANGE_RECD Changed route
- *
- * This routine first extracts pointers to the route destination, netmask and
- * gateway from the <pRouteInfo> parameter. In the case of redirects, the
- * old gateway address is also extracted and then a log message is printed
- * if configured to do so and then this routine exits.
- *
- * If it is a new route, this routine asks RIP to reject all routes except the
- * primary routes. For static routes, it assigns a metric that is the same
- * as the interface index + the interface metric + protocol ID.
- *
- * RETURNS: A metric value (less than HOPCNT_INFINITY), if the route is to
- * be accepted; or HOPCNT_INFINITY, if the route is to be ignored.
- *
- * NOMANUAL
- */
- STATUS ripRouteHook
- (
- ROUTE_INFO * pRouteInfo, /* Route information */
- int protoId, /* Routing protocol ID */
- BOOL primaryRoute, /* Primary route ? */
- int flags /* Whether redirect */
- )
- {
- int ifIndex;
- int metric;
- struct sockaddr * pDstAddr, * pNetmask, * pGateway, * pOldGateway;
- /* Extract the address pointers from the route info structure */
- ripAddrsXtract (pRouteInfo, &pDstAddr, &pNetmask, &pGateway, &pOldGateway);
- /* Get the interface index */
- ifIndex = pRouteInfo->rtm.rtm_index;
- if (routedDebug)
- {
- logMsg ("nripRouteHook: called for proto: %d, ifIndex=%d, Redirect = %s,"
- " Initial metric = %d Primary route=%sn", protoId, ifIndex,
- (int)((flags & RIP_REDIRECT_RECD) ? "Yes" : "No"),
- pRouteInfo->rtm.rtm_rmx.rmx_hopcount,
- (int)(primaryRoute ? "TRUE" : "FALSE"), 0);
- ripSockaddrPrint (pDstAddr);
- ripSockaddrPrint (pNetmask);
- ripSockaddrPrint (pGateway);
- }
- /* If it is a redirect message, print the old gateway and exit */
- if (flags & RIP_REDIRECT_RECD)
- {
- if (routedDebug)
- {
- logMsg ("ripRouteHook: Redirect received fromn", 0, 0, 0, 0, 0, 0);
- ripSockaddrPrint (pOldGateway);
- }
- return (HOPCNT_INFINITY);
- }
- /* If it is a route change message, print the old gateway address */
- if (flags & RIP_ROUTE_CHANGE_RECD)
- {
- if (routedDebug)
- {
- logMsg ("ripRouteHook: route change: Old gateway:n", 0, 0, 0, 0, 0, 0);
- ripSockaddrPrint (pOldGateway);
- }
- }
- /*
- * If it is not a primary route return ERROR to let RIP ignore this
- * route
- */
- if (! primaryRoute)
- return (HOPCNT_INFINITY);
- /*
- * Calculate metric. We give preference to static routes over other routes
- * This is an arbitrary metric that is the sum of protocol ID,
- * interface index and the initial route metric. Since the static route
- * has the lowest protocol ID it gets the lowest metric.
- */
- metric = protoId + ifIndex + pRouteInfo->rtm.rtm_rmx.rmx_hopcount;
- if (metric >= (HOPCNT_INFINITY - 1))
- metric = HOPCNT_INFINITY - 2;
- if (routedDebug)
- logMsg ("ripRouteHook: returning metric %dn", metric, 0, 0, 0, 0, 0);
- return (metric);
- }
- /****************************************************************************
- *
- * ripIfSearch - add new interfaces to the internal list
- *
- * By default, a RIP session will not recognize any interfaces initialized
- * after it has started. This routine schedules a search for additional
- * interfaces that will occur during the next update of the internal routing
- * table. Once completed, the session will accept and send RIP messages over
- * the new interfaces.
- *
- * RETURNS: N/A
- *
- * ERRNO: N/A
- *
- * INTERNAL
- * This routine just sets the flag tested by the watchdog timer handler
- * to trigger a search. Mutual exclusion with that thread is not necessary
- * in this case, since any change will correctly begin the search, which
- * is not time sensitive. However, the actual search routine must lock out
- * all other processing.
- */
- void ripIfSearch (void)
- {
- if (!ripInitFlag)
- return;
- ripState.lookforinterfaces = TRUE;
- }
- /******************************************************************************
- *
- * ripIfReset - alter the RIP configuration after an interface changes
- *
- * This routine updates the interface list and routing tables to reflect
- * address and/or netmask changes for the device indicated by <pIfName>.
- * To accommodate possible changes in the network number, all routes using
- * the named interface are removed from the routing tables, but will be
- * added in the next route update if appropriate. None of the removed
- * routes are poisoned, so it may take some time for the routing tables of
- * all the RIP participants to stabilize if the network number has changed.
- * This routine replaces the existing interface structure with a new one.
- * Thus, any interface specific MIB2 changes that were made to the interface
- * being reset will be lost
- *
- * RETURNS: OK, or ERROR if named interface not found or not added to list.
- *
- * ERRNO: N/A
- *
- * INTERNAL
- * This routine uses the mutex semaphore to block all other RIP processing
- * until the data structures are in a stable state. The internal RIP routing
- * table and the kernel routing table will be updated after it returns. If
- * the network number did not change, all the removed routes received from
- * other RIP sessions are still valid and will be added by the next update.
- */
- STATUS ripIfReset
- (
- char * pIfName /* name of changed interface */
- )
- {
- long ifIndex;
- int slen;
- int tlen;
- BOOL found = FALSE;
- struct interface * pIf; /* Target interface entry, if found. */
- struct interface * pPrevIf;/* Previous interface entry. */
- struct interface * pNextIf;/* Next interface entry. */
- STATUS result = OK;
- if (!ripInitFlag)
- return (ERROR);
- if (pIfName == NULL)
- return (ERROR);
- slen = strlen (pIfName);
- if (slen == 0)
- return (ERROR);
- /* Get the index of the Interface */
- ifIndex = ifNameToIfIndex (pIfName);
- if (ifIndex == 0)
- {
- /*
- * Well, this means that the interface is gone. We just
- * remove its entries in our table
- */
- }
- /*
- * Block access to all processing while updating the interface
- * list and routing tables.
- */
- semTake (ripLockSem, WAIT_FOREVER);
- pPrevIf = ripIfNet;
- for (pIf = ripIfNet; pIf; pIf = pNextIf)
- {
- /*
- * Save the next interface value now as we might delete the
- * interface below.
- */
- pNextIf = pIf->int_next;
- /*
- * Ignore names of different lengths to prevent a false match
- * between overlapping unit numbers such as "ln1" and "ln10".
- */
- tlen = strlen (pIf->int_name);
- if (tlen != slen)
- {
- pPrevIf = pIf;
- continue;
- }
- if (strcmp (pIfName, pIf->int_name) == 0)
- {
- found = TRUE;
- /*
- * Mark the interface down so that ifRouteAdd() will not
- * select this interface
- */
- pIf->int_flags &= ~IFF_UP;
- /*
- * Now delete all routes passing through this interface.
- * including the locally generated entries for accessing the
- * directly connected network
- */
- ripRoutesDelete (pIf, TRUE);
- /* Now delete the interface itself */
- ripInterfaceIntDelete (pIf, pPrevIf);
- }
- else
- pPrevIf = pIf;
- }
- /* If interface was not found, return error */
- if (!found)
- {
- semGive (ripLockSem);
- return (ERROR);
- }
- /*
- * Add the new entry from kernel's list. If ifIndex == 0, that means
- * the interface has been deleted. Don't bother calling routedIfInit
- * if that's the case.
- */
- if (ifIndex != 0)
- result = routedIfInit (FALSE, ifIndex);
- semGive (ripLockSem);
- return (result);
- }
- /******************************************************************************
- *
- * ripFilterEnable - activate strict border gateway filtering
- *
- * This routine configures an active RIP session to enforce the restrictions
- * necessary for RIP-1 and RIP-2 routers to operate correctly in the same
- * network as described in section 3.2 of RFC 1058 and section 3.3 of RFC 1723.
- * When enabled, routes to portions of a logical network (including host
- * routes) will be limited to routers within that network. Updates sent
- * outside that network will only include a single entry representing the
- * entire network. That entry will subsume all subnets and host-specific
- * routes. If supernets are used, the entry will advertise the largest
- * class-based portion of the supernet reachable through the connected
- * interface.
- *
- * RETURNS: N/A
- *
- * ERRNO: N/A
- *
- * INTERNAL
- * This routine allows the supply() routine in ./rip/output.c to call
- * the family-specific sendroute routine that selects the RTS_INTERNAL
- * route entries for transmission outside of a network. The current
- * implementation for AF_INET routes is the inet_sendroute routine in
- * the ./rip/inet.c file.
- */
- void ripFilterEnable (void)
- {
- if (!ripInitFlag)
- return;
- /* Wait for current processing to complete before changing behavior. */
- semTake (ripLockSem, WAIT_FOREVER);
- ripFilterFlag = TRUE;
- semGive (ripLockSem);
- return;
- }
- /******************************************************************************
- *
- * ripFilterDisable - prevent strict border gateway filtering
- *
- * This routine configures an active RIP session to ignore the restrictions
- * necessary for RIP-1 and RIP-2 routers to operate correctly in the same
- * network. All border gateway filtering is ignored and all routes to
- * subnets, supernets, and specific hosts will be sent over any available
- * interface. This operation is only correct if no RIP-1 routers are present
- * anywhere on the network. Results are unpredictable if that condition is
- * not met, but high rates of packet loss and widespread routing failures are
- * likely.
- *
- * The border gateway filtering rules are in force by default.
- *
- * RETURNS: N/A
- *
- * ERRNO: N/A
- *
- * INTERNAL
- * This routine prevents the supply() routine in ./rip/output.c from executing
- * the family-specific sendroute routine that limits the propagation
- * of internal network information. The current implementation for AF_INET
- * routes is the inet_sendroute routine in the ./rip/inet.c file.
- */
- void ripFilterDisable (void)
- {
- if (!ripInitFlag)
- return;
- semTake (ripLockSem, WAIT_FOREVER);
- ripFilterFlag = FALSE;
- semGive (ripLockSem);
- return;
- }
- /******************************************************************************
- *
- * ripShutdown - terminate all RIP processing
- *
- * This routine "poisons" all routes in the current table by transmitting
- * updates with an infinite metric for each entry over all available
- * interfaces. It then halts all RIP processing and removes the associated
- * tasks and data structures. When completed successfully, the RIP
- * services are unavailable until restarted with the ripLibInit() routine.
- *
- * RETURNS: OK if shutdown completed, or ERROR otherwise.
- *
- * ERRNO: N/A
- *
- * INTERNAL
- * The ripState global is not changed by this routine so that the system
- * status can still be examined before restarting. That global is cleared
- * by the initialization routine.
- */
- STATUS ripShutdown (void)
- {
- register struct rthash *rh;
- register struct interface *ifp, *pTemp;
- register struct rt_entry *rt;
- struct rthash *base = hosthash;
- int doinghost = 1;
- #ifdef RIP_MD5
- RIP_AUTH_KEY * pAuth;
- #endif /* RIP_MD5 */
- #ifndef VIRTUAL_STACK
- IMPORT RIP ripState;
- #endif
- if (!ripInitFlag)
- return (OK);
- /*
- * Obtain the lock semaphore to synchronize the shutdown with the
- * timer and message processing threads.
- */
- semTake (ripLockSem, WAIT_FOREVER);
- /*
- * Remove the watchdog timer and RIP tasks to prevent further updates
- * and eliminate the mutex semaphore. The timer task must be removed
- * first to prevent an invalid reference to the watchdog.
- */
- taskDelete (ripState.ripTimerTaskId);
- wdCancel (ripState.timerDog);
- wdDelete (ripState.timerDog);
- taskDelete (ripState.ripTaskId);
- semDelete (ripLockSem);
- /* Set the route hook to NULL */
- ripState.pRouteHook = NULL;
- /*
- * Poison all known routes to signal neighboring RIP
- * routers of pending exit.
- */
- if (ripState.supplier)
- {
- again:
- for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++)
- {
- rt = rh->rt_forw;
- for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw)
- rt->rt_metric = HOPCNT_INFINITY;
- }
- if (doinghost)
- {
- doinghost = 0;
- base = nethash;
- goto again;
- }
- toall (supply, 0, (struct interface *)NULL);
- }
- /* Remove all entries from the kernel and RIP routing tables. */
- rtdeleteall ();
- /* Remove list of available interfaces. */
- ifp = ripIfNet;
- while (ifp != NULL)
- {
- pTemp = ifp;
- ifp = pTemp->int_next;
- #ifdef RIP_MD5
- /* free the auth keys for this interface */
- pAuth = pTemp->pAuthKeys;
- while (pAuth != NULL)
- {
- pTemp->pAuthKeys = pAuth->pNext;
- free (pAuth);
- pAuth = pTemp->pAuthKeys;
- }
- #endif /* RIP_MD5 */
- free (pTemp);
- }
- /* Free up the RIP interface exclusion list */
- lstFree (&ripIfExcludeList);
- /* Remove the remaining data structures and the input/output socket. */
- semDelete (ripState.timerSem);
- close (ripState.s);
- close (ripState.routeSocket);
- /* Set ripInitFlag to FALSE now that we have uninitialized RIP */
- ripInitFlag = FALSE;
- return (OK);
- }
- /******************************************************************************
- *
- * ripDebugLevelSet - specify amount of debugging output
- *
- * This routine determines the amount of debugging information sent to
- * standard output during the RIP session. Higher values of the <level>
- * parameter result in increasingly verbose output. A <level> of zero
- * restores the default behavior by disabling all debugging output.
- *
- * RETURNS: N/A
- *
- * ERRNO: N/A
- */
- void ripDebugLevelSet
- (
- int level /* verbosity level (0 - 3) */
- )
- {
- /* Disable debugging if a bogus value is given. */
- if (level < 0 || level > 3)
- level = 0;
- routedDebug = level;
- }
- #ifdef RIP_MD5
- /***************************************************************************
- *
- * ripAuthKeyShow - show current authentication configuration
- *
- * This routines shows the current configuration of the authentication keys
- * for each interface.
- *
- * RETURNS: N/A
- */
- void ripAuthKeyShow
- (
- UINT showKey /* if non-zero then key values are shown */
- )
- {
- register RIP_AUTH_KEY * pAuthKey;
- register struct interface *ifp;
- time_t t;
- semTake (ripLockSem, WAIT_FOREVER);
- printf ("n%-10s %-9s %-10s %-15s %-24sn",
- "Interface", "KeyID", "Protocol", "Expires", "Key");
- printf ("----------------------------------------------------------------"
- "----------n");
- t = time (NULL);
- for (ifp = ripIfNet; ifp; ifp = ifp->int_next)
- {
- for (pAuthKey = ifp->pAuthKeys; pAuthKey; pAuthKey = pAuthKey->pNext)
- {
- printf ("%-10s ", ifp->int_name);
- printf ("%-9u ", pAuthKey->keyId);
- if (pAuthKey->authProto == RIP_AUTH_PROTO_MD5)
- printf ("%-10s ", "MD5");
- else if (pAuthKey->authProto == RIP_AUTH_PROTO_SHA1)
- printf ("%-10s ", "SHA-1");
- else
- printf ("%-10s ", "unknown");
- if (pAuthKey->timeEnd > t)
- printf ("%-15lu ", (pAuthKey->timeEnd - t));
- else
- printf ("%-15s ", "expired");
- if (showKey)
- printf ("%-24sn", pAuthKey->pKey);
- else
- printf ("<not shown>n");
- }
- }
- printf ("n");
- semGive (ripLockSem);
- }
- /***************************************************************************
- *
- * ripAuthKeyAdd - add a new RIP authentication key
- *
- * This routine is used to add a new RIP authentication key for a specific
- * interface.
- *
- * RETURNS: ERROR, if the interface does not exist, or the <keyId> already
- * exists, or if the protocol is not supported; OK, if key was entered.
- */
- STATUS ripAuthKeyAdd
- (
- char * pInterfaceName, /* interface to add a key */
- UINT16 keyId, /* the keyId for this new key */
- char * pKey, /* the secret key */
- UINT keyLen, /* length of the secret key */
- UINT authProto, /* auth protocol to use (1 = MD5) */
- ULONG timeValid /* number of seconds until key expires */
- )
- {
- register struct interface *ifp;
- register RIP_AUTH_KEY * pAuthKey;
- RIP_AUTH_KEY * pNewAuthKey;
- if (authProto != RIP_AUTH_PROTO_MD5) return ERROR;
- semTake (ripLockSem, WAIT_FOREVER);
- for (ifp = ripIfNet; ifp; ifp = ifp->int_next)
- {
- if (strcmp (pInterfaceName, ifp->int_name) == 0)
- {
- for (pAuthKey = ifp->pAuthKeys; pAuthKey;
- pAuthKey = pAuthKey->pNext)
- {
- if (pAuthKey->keyId == keyId)
- {
- semGive (ripLockSem);
- return ERROR;
- }
- }
- pNewAuthKey = malloc (sizeof (RIP_AUTH_KEY));
- if (pNewAuthKey == NULL)
- {
- semGive (ripLockSem);
- return ERROR;
- }
- memset (pNewAuthKey, 0, sizeof (RIP_AUTH_KEY));
- pNewAuthKey->keyId = keyId;
- pNewAuthKey->authProto = authProto;
- pNewAuthKey->timeStart = time (NULL);
- pNewAuthKey->timeEnd = (pNewAuthKey->timeStart + timeValid);
- memcpy (pNewAuthKey->pKey, pKey, keyLen);
- pNewAuthKey->ifp = ifp;
- pNewAuthKey->pNext = ifp->pAuthKeys;
- ifp->pAuthKeys = pNewAuthKey;
- semGive (ripLockSem);
- return OK;
- }
- }
- semGive (ripLockSem);
- return ERROR;
- }
- /***************************************************************************
- *
- * ripAuthKeyDelete - delete an existing RIP authentication key
- *
- * This routine is used to delete a RIP authentication key for a specific
- * interface.
- *
- * RETURNS: ERROR, if the interface does not exist, or the <keyId> does not
- * exist; OK, if key was deleted.
- */
- STATUS ripAuthKeyDelete
- (
- char * pInterfaceName, /* interface to delete a key from */
- UINT16 keyId /* the keyId of the key to delete */
- )
- {
- register struct interface *ifp;
- register RIP_AUTH_KEY * pPrevAuthKey;
- register RIP_AUTH_KEY * pAuthKey;
- semTake (ripLockSem, WAIT_FOREVER);
- for (ifp = ripIfNet; ifp; ifp = ifp->int_next)
- {
- if (strcmp (pInterfaceName, ifp->int_name) == 0)
- {
- if (ifp->pAuthKeys == NULL)
- {
- semGive (ripLockSem);
- return ERROR;
- }
- pPrevAuthKey = ifp->pAuthKeys;
- pAuthKey = pPrevAuthKey->pNext;
- if (pPrevAuthKey->keyId == keyId)
- {
- ifp->pAuthKeys = pAuthKey;
- free (pPrevAuthKey);
- semGive (ripLockSem);
- return OK;
- }
- while (pAuthKey)
- {
- if (pAuthKey->keyId == keyId)
- {
- pPrevAuthKey->pNext = pAuthKey->pNext;
- free (pAuthKey);
- semGive (ripLockSem);
- return OK;
- }
- pPrevAuthKey = pAuthKey;
- pAuthKey = pAuthKey->pNext;
- }
- semGive (ripLockSem);
- return ERROR;
- }
- }
- semGive (ripLockSem);
- return ERROR;
- }
- /***************************************************************************
- *
- * ripAuthKeyFind - find a RIP authentication key
- *
- * This routine is used to find a RIP authentication key based on a specified
- * interface and keyId. When a key is found, a pointer to the RIP_AUTH_KEY
- * struct for the key is stored in pKey.
- *
- * RETURNS: ERROR, if the key is not found; OK if the key was found.
- */
- STATUS ripAuthKeyFind
- (
- struct interface * ifp, /* interface to search for key */
- UINT16 keyId, /* the keyId of the key to search for */
- RIP_AUTH_KEY ** pKey /* storage for the key data */
- )
- {
- register RIP_AUTH_KEY * pAuthKey;
- for (pAuthKey = ifp->pAuthKeys; pAuthKey; pAuthKey = pAuthKey->pNext)
- {
- if (pAuthKey->keyId == keyId)
- {
- *pKey = pAuthKey;
- return OK;
- }
- }
- return ERROR;
- }
- /***************************************************************************
- *
- * ripAuthKeyFindFirst - find a RIP authentication key
- *
- * This routine is used to find a RIP authentication key based on a specified
- * interface. Because a <keyId> is not specified, this routine returns the
- * first non-expired key found for the interface. When a key is found, a
- * pointer to the RIP_AUTH_KEY structure for the key is returned in <pKey>.
- *
- * RETURNS: ERROR, if a key is not found; OK, if a key was found.
- */
- STATUS ripAuthKeyFindFirst
- (
- struct interface * ifp, /* interface to search for key */
- RIP_AUTH_KEY ** pKey /* storage for the key data */
- )
- {
- register RIP_AUTH_KEY * pAuthKey;
- RIP_AUTH_KEY * pBackup;
- time_t t;
- /*
- * Save an available key for possible use if no valid entries exist,
- * regardless of the expiration time (RFC 2082, section 4.3).
- */
- pBackup = ifp->pAuthKeys;
- if (pBackup == NULL)
- {
- logMsg ("RIP: Error! No MD5 keys available!", 0, 0, 0, 0, 0, 0);
- return (ERROR);
- }
- /* check that the key has not yet expired */
- t = time (NULL);
- for (pAuthKey = ifp->pAuthKeys; pAuthKey; pAuthKey = pAuthKey->pNext)
- {
- if (pAuthKey->timeEnd > t)
- {
- *pKey = pAuthKey;
- return OK;
- }
- }
- /*
- * All keys expired! Send notification to network manager and treat
- * available key as having an infinite lifetime (RFC 2082, section 4.3).
- */
- logMsg ("RIP: Warning! Last authentication key expired. Using key ID %x.n",
- pBackup->keyId, 0, 0, 0, 0, 0);
- *pKey = pBackup;
- return ERROR;
- }
- /***************************************************************************
- *
- * ripAuthKeyInMD5 - authenticate an incoming RIP-2 message using MD5
- *
- * This routine is used to authenticate an incoming RIP-2 message using
- * the MD5 digest protocol. This authentication scheme is described in
- * RFC 2082.
- *
- * RETURNS: ERROR, if could not authenticate; OK, if authenticated.
- */
- STATUS ripAuthKeyInMD5
- (
- struct interface * ifp, /* interface message received on */
- RIP_PKT * pRip, /* received RIP message */
- UINT size /* length of the RIP message */
- )
- {
- RIP2_AUTH_PKT_HDR * pAuthHdr;
- RIP2_AUTH_PKT_TRL * pAuthTrl;
- RIP_AUTH_KEY * pAuthKey;
- UCHAR savedDigest [MD5_DIGEST_LEN];
- UCHAR newDigest [MD5_DIGEST_LEN];
- UINT numRipEntries;
- MD5_CTX_T context;
- time_t t;
- /* must be a RIP version 2 packet */
- if (pRip->rip_vers == 1)
- return ERROR;
- pAuthHdr = (RIP2_AUTH_PKT_HDR *)pRip->rip_nets;
- /* check basic auth header fields */
- if ((pAuthHdr->authIdent != RIP2_AUTH) ||
- (ntohs (pAuthHdr->authType) != M2_rip2IfConfAuthType_md5) ||
- (pAuthHdr->zero1 != 0) || (pAuthHdr->zero2 != 0))
- return ERROR;
- /* get the secret key for the given keyid for this interface */
- if (ripAuthKeyFind (ifp, pAuthHdr->keyId, &pAuthKey) == ERROR)
- return ERROR;
- /* check that the key has not yet expired */
- t = time (NULL);
- if (pAuthKey->timeEnd <= t)
- return ERROR;
- /* check that MD5 is being used for this key and the authDataLen is 16 */
- if ((pAuthKey->authProto != RIP_AUTH_PROTO_MD5) ||
- (pAuthHdr->authDataLen != MD5_DIGEST_LEN))
- return ERROR;
- /* make sure the trailing digest is the correct length */
- if ((size - (ntohs (pAuthHdr->packetLen) + 4)) != MD5_DIGEST_LEN)
- return ERROR;
- /* make sure all RIP entries are 20 bytes long */
- if (((ntohs (pAuthHdr->packetLen) - 24) % 20) != 0)
- return ERROR;
- /* get the number of RIP entries including the auth header */
- numRipEntries = ((ntohs (pAuthHdr->packetLen) - 24) / 20);
- /* get the auth trailer that includes the message digest */
- pAuthTrl = (RIP2_AUTH_PKT_TRL *)(pAuthHdr + 1 + numRipEntries);
- /* check basic auth trailer fields */
- if ((pAuthTrl->authIdent != RIP2_AUTH) ||
- ((ntohs (pAuthTrl->authTag) != 0x01) &&
- (ntohs (pAuthTrl->authTag) != M2_rip2IfConfAuthType_md5)))
- return ERROR;
- /* save the old digest */
- memcpy (savedDigest, pAuthTrl->authDigest, MD5_DIGEST_LEN);
- /* write the secret key over the digest in the packet */
- memcpy (pAuthTrl->authDigest, pAuthKey->pKey, MD5_DIGEST_LEN);
- /* compute the MD5 authentication digest */
- memset (&context, 0, sizeof (MD5_CTX_T));
- MD5Init (&context);
- MD5Update (&context, (UCHAR *)pRip, size);
- MD5Final (newDigest, &context);
- /* check if the message is authentic by comparing the digests */
- if (memcmp (savedDigest, newDigest, MD5_DIGEST_LEN) != 0)
- return ERROR;
- /*
- * check that the sequence number is greater than the last received
- * make sure this check is done after the message is authenticated
- */
- if ((ntohl (pAuthHdr->sequence) != 0) &&
- (ntohl (pAuthHdr->sequence) <= pAuthKey->lastRcvSequence))
- return ERROR;
- /* save the new recieved sequence number */
- pAuthKey->lastRcvSequence = ntohl (pAuthHdr->sequence);
- return OK; /* Gee wiz... */
- }
- /***************************************************************************
- *
- * ripAuthKeyOut1MD5 - start MD5 authentication of an outgoing RIP-2 message
- *
- * This routine is used to start the authentication of an outgoing RIP-2
- * message by adding the authentication header used for MD5 authentication.
- * This authentication scheme is described in RFC 2082. This function
- * returns a pointer the authentication header and a pointer to the looked up
- * authentication key.
- *
- * RETURNS: ERROR, if a key could not be found; OK, if the header was added.
- */
- STATUS ripAuthKeyOut1MD5
- (
- struct interface * pIfp, /* interface message being sent on */
- struct netinfo * pNetinfo, /* pointer to next RIP entry to fill in */
- RIP2_AUTH_PKT_HDR ** ppAuthHdr, /* stores the authentication header */
- RIP_AUTH_KEY ** ppAuthKey /* stores the authentication key to use */
- )
- {
- /* get the first RIP entry for storing auth data */
- *ppAuthHdr = (RIP2_AUTH_PKT_HDR *)pNetinfo;
- memset (*ppAuthHdr, 0, sizeof (RIP2_AUTH_PKT_HDR));
- /* fill in the auth tag and type */
- (*ppAuthHdr)->authIdent = RIP2_AUTH;
- (*ppAuthHdr)->authType = htons (M2_rip2IfConfAuthType_md5);
- /* the packet len will be filled in later (in ripAuthKeyOut2MD5) */
- /* get a secret key for this interface */
- if (ripAuthKeyFindFirst (pIfp, ppAuthKey) == ERROR)
- return ERROR;
- /* fill in the keyId and authDataLen */
- (*ppAuthHdr)->keyId = (*ppAuthKey)->keyId;
- if ((*ppAuthKey)->authProto != RIP_AUTH_PROTO_MD5)
- return ERROR;
- (*ppAuthHdr)->authDataLen = MD5_DIGEST_LEN;
- /*
- * Fill in the sequence number. If the last sent is 0 then
- * no RIP message has been sent out this interface. So 0 must
- * be sent as the sequence number.
- */
- if ((*ppAuthKey)->lastSntSequence == 0)
- (*ppAuthHdr)->sequence = 0;
- else
- (*ppAuthHdr)->sequence = htonl ((*ppAuthKey)->lastSntSequence + 1);
- (*ppAuthKey)->lastSntSequence++;
- return OK;
- }
- /***************************************************************************
- *
- * ripAuthKeyOut2MD5 - authenticate an outgoing RIP-2 message using MD5
- *
- * This routine is used to authenticate an outgoing RIP-2 message using
- * the MD5 digest protocol. This authentication scheme is described in
- * RFC 2082. This function modifies the size given in pSize to account
- * for the extra auth trailer data. The auth trailer is appended to the
- * given RIP_PKT and the authentication digest is filled in.
- *
- * RETURNS: N/A
- */
- void ripAuthKeyOut2MD5
- (
- RIP_PKT * pRip, /* RIP message to authenticate */
- UINT * pSize, /* length of the RIP message */
- struct netinfo * pNetinfo, /* pointer to next RIP entry to fill in */
- RIP2_AUTH_PKT_HDR * pAuthHdr, /* pointer to auth header in the message */
- RIP_AUTH_KEY * pAuthKey /* the auth key data to use */
- )
- {
- RIP2_AUTH_PKT_TRL * pAuthTrl;
- MD5_CTX_T context;
- UCHAR newDigest [MD5_DIGEST_LEN];
- /* get the last RIP entry for storing the auth digest */
- pAuthTrl = (RIP2_AUTH_PKT_TRL *)pNetinfo;
- memset (pAuthTrl, 0, sizeof (RIP2_AUTH_PKT_TRL));
- /* fill in the packet len located in the auth header */
- pAuthHdr->packetLen = htons ((UINT16)*pSize);
- /* increment the size to show the auth trailer */
- *pSize += sizeof (struct netinfo);
- /* fill in the auth tag and type */
- pAuthTrl->authIdent = RIP2_AUTH;
- pAuthTrl->authTag = htons (0x01);
- /* copy in the secret key into the auth trailer */
- memcpy (pAuthTrl->authDigest, pAuthKey->pKey, MD5_DIGEST_LEN);
- /* compute the digest and store it in the auth trailer */
- memset (&context, 0, sizeof (MD5_CTX_T));
- MD5Init (&context);
- MD5Update (&context, (UCHAR *)pRip, *pSize);
- MD5Final (newDigest, &context);
- memcpy (pAuthTrl->authDigest, newDigest, MD5_DIGEST_LEN);
- }
- #endif /* RIP_MD5 */
- #ifdef ROUTER_STACK
- LOCAL BOOL ripRouteSame
- (
- struct rt_entry * pRtEntry, /* RIP Route entry to compare */
- struct sockaddr * pDstAddr, /* Destination addr to compare with */
- struct sockaddr * pNetmask, /* Netmask to compare with */
- struct sockaddr * pGateway /* Gateway to compare with */
- )
- {
- struct sockaddr netmask;
- struct sockaddr_in * pNsin;
- if (routedDebug)
- {
- logMsg ("nnripRouteSame: route entry:n", 0, 0, 0, 0, 0, 0);
- ripSockaddrPrint (&pRtEntry->rt_dst);
- ripSockaddrPrint (&pRtEntry->rt_netmask);
- ripSockaddrPrint (&pRtEntry->rt_router);
- logMsg ("ripRouteSame: to be compared entry:n", 0, 0, 0, 0, 0, 0);
- ripSockaddrPrint (pDstAddr);
- ripSockaddrPrint (pNetmask);
- ripSockaddrPrint (pGateway);
- logMsg ("nn", 0, 0, 0, 0, 0, 0);
- }
- /* If destination values differ, return FALSE */
- if (!equal (pDstAddr, &pRtEntry->rt_dst))
- return (FALSE);
- /*
- * If the gateway value is specified, then
- * compare the gateway value we have in the route entry.
- * If the gateway value is not specified, then this is a primary route
- * that is being changed. Check that the route entry we have is also for
- * the primary route. If not, the routes don't match.
- */
- if (pGateway)
- {
- if (!equal (pGateway, &pRtEntry->rt_router))
- return (FALSE);
- }
- else
- {
- if (! (pRtEntry->rt_state & RTS_PRIMARY))
- return (FALSE);
- }
- /*
- * We always store the netmask of a default route as all zeros.
- * So if it is a default route, we need only compare the destination
- * and gateway address fields
- */
- if (((struct sockaddr_in *)&(pRtEntry->rt_dst))->sin_addr.s_addr == 0)
- return (TRUE);
- /*
- * If netmask is specified, check that they match. We
- * check only the address part as thge prefix part sometimes
- * differs
- */
- if (pNetmask)
- return (SOCKADDR_IN (pNetmask) == SOCKADDR_IN (&pRtEntry->rt_netmask));
- /*
- * If no netmask was specified, we calculated the netmask to be that
- * of the interface. Check for that case
- */
- bzero ((char *)&netmask, sizeof (netmask));
- netmask.sa_family = AF_INET;
- netmask.sa_len = 16;
- pNsin = (struct sockaddr_in *)&netmask;
- pNsin->sin_addr.s_addr = htonl (pRtEntry->rt_ifp->int_subnetmask);
- return (equal (&netmask, &pRtEntry->rt_netmask));
- }
- /***************************************************************************
- *
- * ripInterfaceUpFlagSet - set or reset the interface UP flag
- *
- * This function sets or resets the IFF_UP flag of the interface specified
- * by <pIfName> according to the status described by <up>. If the interface
- * is being set up, it also adds the interface routes the interface,
- * else if the interface is being brought down, it deletes all routes
- * passing through the interface except the routes learned through the
- * Routing system callback.
- *
- * RETURNS: OK or ERROR.
- *
- * NOMANUAL
- *
- * INTERNAL
- * This routine loops through the entire interface table looking for
- * interfaces with the specified name. A single IP interface with aliases
- * is stored by RIP as multiple interface with the same name (but different
- * addresses). Hence the looping is needed.
- */
- LOCAL STATUS ripInterfaceUpFlagSet
- (
- u_short ifIndex,
- BOOL up
- )
- {
- int error = ERROR;
- struct interface * pIf; /* Target interface entry, if found. */
- if (ifIndex == 0)
- return (ERROR);
- if (routedDebug)
- logMsg ("ripInterfaceUpFlagSet: Setting %d %sn",
- ifIndex, (int)(up ? "UP" : "DOWN"), 0, 0, 0, 0);
- /*
- * Now loop through our interface list and set the flag of all matching
- * interfaces. We might have more than one interface match a given
- * index if the interface is aliased. We treat each alias as a separate
- * interface.
- */
- for (pIf = ripIfNet; pIf; pIf = pIf->int_next)
- {
- if (ifIndex == pIf->int_index)
- {
- if (up && (pIf->int_flags & IFF_UP) == 0)
- {
- pIf->int_flags |= IFF_UP;
- /*
- * Now add a route to the local network. This will delete
- * any non-interface routes that we might have learned
- * for the network while we were down
- */
- addrouteforif (pIf);
- }
- else if (!up && (pIf->int_flags & IFF_UP) == IFF_UP)
- {
- pIf->int_flags &= ~IFF_UP;
- /*
- * Now delete all routes that pass through this interface.
- * Don't delete the STATIC or non-RIP routes that we learned
- * for this interface (through the Routing system callback
- * as we will never ever re-learn them
- */
- ripRoutesDelete (pIf, FALSE);
- }
- error = OK;
- }
- }
- return (error);
- }
- #endif /* ROUTER_STACK */
- /***************************************************************************
- *
- * ripRoutesDelete - delete routes passing through an interface
- *
- * This function deletes all routes passing though the interface specified
- * by the <pIf> parameter. If the deleteAllRoutes parameter is set to FALSE,
- * then only the routes that were added by us (the interface routes and routes
- * learned from our peers) are deleted. The Static and other routing protocol
- * routes (like OSPF) learned through the routing syste, callback are not
- * deleted.
- *
- * RETURNS: OK or ERROR
- *
- * NOMANUAL
- */
- LOCAL STATUS ripRoutesDelete
- (
- struct interface * pIf,
- BOOL deleteAllRoutes
- )
- {
- struct rt_entry * rt;
- struct sockaddr * dst;
- struct rthash * pHashList; /* Individual hash table entry. */
- struct rt_entry * pRt; /* Individual route entry. */
- struct sockaddr_in net;
- int error = ERROR;
- if (!(pIf->int_flags & IFF_ROUTES_DELETED))
- {
- pIf->int_flags |= IFF_ROUTES_DELETED;
- /*
- * If the interface is subnetted, then we must have added
- * (or incremented ref count on) the class based network route.
- * If we added the route, then that will be taken care of in
- * rt_delete(). If we just increased the refcnt, then we need to
- * decrease the refcnt
- */
- if (!(pIf->int_flags & IFF_POINTOPOINT) &&
- pIf->int_netmask != pIf->int_subnetmask)
- {
- /* look for route to logical network */
- memset(&net, 0, sizeof (net));
- net.sin_len = sizeof (net);
- net.sin_family = AF_INET;
- net.sin_addr.s_addr = htonl (pIf->int_net);
- dst = (struct sockaddr *)&net;
- rt = rtlookup(dst);
- if (rt && rt->rt_ifp != pIf)
- {
- /*
- * We didn't add the route, just incremented the ref count.
- * Decrement the ref counts now
- */
- rt->rt_refcnt--;
- rt->rt_subnets_cnt--;
- }
- }
- /*
- * Now check if we added the network (remote, for PPP links)
- * route. If we did, then no need to do anything as rtdelete will
- * handle the route deletion. If we didn't add the route, then
- * we must've increased the ref count. We need to decrement the ref
- * count now that we will not be referencing it any more.
- */
- if (pIf->int_flags & IFF_POINTOPOINT)
- dst = &pIf->int_dstaddr;
- else
- {
- memset(&net, 0, sizeof (net));
- net.sin_len = sizeof (net);
- net.sin_family = AF_INET;
- net.sin_addr.s_addr = htonl (pIf->int_subnet);
- dst = (struct sockaddr *)&net;
- }
- if ((rt = rtlookup(dst)) == NULL)
- rt = rtfind(dst);
- if (rt && rt->rt_ifp != pIf)
- rt->rt_refcnt--;
- /*
- * For a point to point link, we either added a route for the
- * local end of the link, or incremented the reference count
- * on an existing route. If there are no other references to that
- * route, delete it, else just decrement the reference count
- * NOTE: He we don't check for the interface, as the interface is
- * the same (loopback) for all instances of this route
- */
- if (pIf->int_flags & IFF_POINTOPOINT)
- {
- dst = &pIf->int_addr;
- if ((rt = rtlookup(dst)) == NULL)
- rt = rtfind(dst);
- if (rt)
- {
- if (rt->rt_refcnt == 0)
- rtdelete (rt);
- else
- rt->rt_refcnt--;
- }
- }
- }
- /*
- * Remove any routes associated with the changed interface from
- * both hash tables.
- */
- for (pHashList = hosthash; pHashList < &hosthash [ROUTEHASHSIZ];
- pHashList++)
- {
- pRt = pHashList->rt_forw;
- for (; pRt != (struct rt_entry *)pHashList; pRt = pRt->rt_forw)
- {
- if (pRt->rt_ifp != pIf)
- continue;
- if (!deleteAllRoutes && ((pRt->rt_state & RTS_OTHER) != 0))
- continue;
- pRt = pRt->rt_back;
- rtdelete (pRt->rt_forw);
- error = OK;
- }
- }
- for (pHashList = nethash; pHashList < &nethash [ROUTEHASHSIZ]; pHashList++)
- {
- pRt = pHashList->rt_forw;
- for (; pRt != (struct rt_entry *)pHashList; pRt = pRt->rt_forw)
- {
- if (pRt->rt_ifp != pIf)
- continue;
- if (!deleteAllRoutes && ((pRt->rt_state & RTS_OTHER) != 0))
- continue;
- pRt = pRt->rt_back;
- rtdelete (pRt->rt_forw);
- error = OK;
- }
- }
- return (error);
- }
- #ifdef ROUTER_STACK
- /***************************************************************************
- *
- * ripInterfaceDelete - delete the interface
- *
- * This function deletes the interface structure pointed to by <pIf>
- * and frees the memory associated with it. This function is actually
- * a wrapper for the ripInterfaceIntDelete() call that actually deletes
- * the interface.
- *
- * RETURNS: OK or ERROR
- *
- * NOMANUAL
- *
- */
- LOCAL STATUS ripInterfaceDelete
- (
- struct interface * pIf
- )
- {
- struct interface * pTmpIf;
- struct interface * pPrevIf;
- /* Search for the interface in our list */
- pPrevIf = ripIfNet;
- for (pTmpIf = ripIfNet; pTmpIf && pTmpIf != pIf; pTmpIf = pTmpIf->int_next)
- pPrevIf = pTmpIf;
- if (pTmpIf == NULL)
- return (ERROR);
- return (ripInterfaceIntDelete (pIf, pPrevIf));
- }
- #endif /* ROUTER_STACK */
- /***************************************************************************
- *
- * ripInterfaceIntDelete - delete the interface
- *
- * This function deletes the interface structure pointed to by <pIf>
- * from the list of interfaces and frees the memory associated with
- * the interface.
- *
- * RETURNS: OK or ERROR
- *
- * NOMANUAL
- *
- */
- LOCAL STATUS ripInterfaceIntDelete
- (
- struct interface * pIf,
- struct interface * pPrevIf
- )
- {
- #ifdef RIP_MD5
- RIP_AUTH_KEY * pAuth;
- #endif /* RIP_MD5 */
- /* Reset head of the list if necessary. */
- if (pIf == ripIfNet)
- ripIfNet = pIf->int_next;
- else
- pPrevIf->int_next = pIf->int_next;
- /*
- * If the matching interface is the last entry in the list, reset
- * the (global) tail pointer so the list will rebuild correctly.
- */
- if (pIf->int_next == NULL)
- {
- /*
- * Set tail pointer to head of list if the matching interface
- * is the only entry. Otherwise set it to the next field of
- * the new list tail (which currently points to NULL).
- */
- if (ripIfNet == NULL) /* Only entry in list? */
- ifnext = &ripIfNet;
- else
- ifnext = &pPrevIf->int_next;
- }
- #ifdef RIP_MD5
- /* free the auth keys for this interface */
- pAuth = pIf->pAuthKeys;
- while (pAuth != NULL)
- {
- pIf->pAuthKeys = pAuth->pNext;
- free (pAuth);
- pAuth = pIf->pAuthKeys;
- }
- #endif /* RIP_MD5 */
- free (pIf);
- return (OK);
- }
- /***************************************************************************
- *
- * ripIfExcludeListAdd - Add an interface to the RIP exclusion list
- *
- * This function adds the interface specified by <ifName> to a list of
- * interfaces on which RIP will not be started. This can be used to
- * prevent RIP from starting on an interface.
- *
- * RETURNS: OK if the interface was successfully added to the list;
- * ERROR otherwise.
- *
- * NOTE: This command must be issued prior to the interface being added
- * to the system, as RIP starts on an interface, unless it has been
- * excluded, as soon as an interface comes up.
- * If RIP was already running on the interface which is now desired
- * to be excluded from RIP, the ripIfReset command should be used
- * after the ripIfExcludeListAdd command.
- */
- STATUS ripIfExcludeListAdd
- (
- char * pIfName /* name of interface to be excluded */
- )
- {
- RT_IFLIST * pIfList;
- int slen;
- if (pIfName == NULL)
- return (ERROR);
- slen = strlen (pIfName);
- if (slen == 0 || slen >= IFNAMSIZ)
- return (ERROR);
- pIfList = (RT_IFLIST *)malloc (sizeof (RT_IFLIST));
- if (pIfList == NULL)
- return (ERROR);
- strcpy (pIfList->rtif_name, pIfName);
- /*
- * Insert the interface in the list of interfaces on which RIP is not
- * to be started
- */
- lstAdd (&ripIfExcludeList, &(pIfList->node));
- return (OK);
- }
- /***************************************************************************
- *
- * ripIfExcludeListDelete - Delete an interface from RIP exclusion list
- *
- * This function deletes the interface specified by <ifName> from the list of
- * interfaces on which RIP will not be started. That is, RIP will start on the
- * interface when it is added or comes up.
- *
- * RETURNS: OK if the interface was successfully removed from the list;
- * ERROR otherwise.
- *
- * NOTE: RIP will not automatically start on the interface. The ripIfSearch()
- * call will need to be made after this call to cause RIP to start on
- * this interface.
- *
- */
- STATUS ripIfExcludeListDelete
- (
- char * pIfName /* name of un-excluded interface */
- )
- {
- RT_IFLIST * pIfList;
- int slen;
- if (pIfName == NULL)
- return (ERROR);
- slen = strlen (pIfName);
- if (slen == 0 || slen >= IFNAMSIZ)
- return (ERROR);
- for (pIfList = (RT_IFLIST *)lstFirst (&ripIfExcludeList);
- pIfList != NULL; pIfList = (RT_IFLIST *)lstNext (&pIfList->node))
- {
- if (slen == strlen (pIfList->rtif_name) &&
- strcmp (pIfName, pIfList->rtif_name) == 0)
- {
- /*
- * Delete the interface from the list of interfaces on
- * which RIP is not to be started
- */
- lstDelete (&ripIfExcludeList, &pIfList->node);
- free ((char *)pIfList);
- return (OK);
- }
- }
- return (ERROR);
- }
- /***************************************************************************
- *
- * ripIfExcludeListCheck - Check if an interface is on the RIP exclusion list
- *
- * This function checks if the interface specified by <ifName> is on the
- * RIP exclusion list.
- *
- * RETURNS: OK if the interface exists on the list; ERROR otherwise.
- *
- * NOMANUAL
- */
- STATUS ripIfExcludeListCheck
- (
- char * pIfName /* name of interface to check*/
- )
- {
- RT_IFLIST * pIfList;
- int slen;
- if (pIfName == NULL)
- return (ERROR);
- slen = strlen (pIfName);
- if (slen == 0 || slen >= IFNAMSIZ)
- return (ERROR);
- for (pIfList = (RT_IFLIST *)lstFirst (&ripIfExcludeList);
- pIfList != NULL; pIfList = (RT_IFLIST *)lstNext (&pIfList->node))
- {
- if (slen == strlen (pIfList->rtif_name) &&
- strcmp (pIfName, pIfList->rtif_name) == 0)
- {
- return (OK);
- }
- }
- return (ERROR);
- }
- /***************************************************************************
- *
- * ripIfExcludeListShow - Show the RIP interface exclusion list
- *
- * This function prints out the interfaces on which RIP will not be started.
- *
- * RETURNS: Nothing
- *
- */
- void ripIfExcludeListShow (void)
- {
- RT_IFLIST * pIfList;
- printf ("List of interfaces on which RIP will not be started:n");
- for (pIfList = (RT_IFLIST *)lstFirst (&ripIfExcludeList);
- pIfList != NULL; pIfList = (RT_IFLIST *)lstNext (&pIfList->node))
- printf ("%sn", pIfList->rtif_name);
- printf ("n");
- }