Files
m241Neelima/components/ip_net2-6.9/vxcompat/src/oldRouteLib.c
T
2026-07-30 11:19:44 +05:30

1171 lines
33 KiB
C

/* oldRouteLib.c - Maintain backward compatibility with obsolete API */
/* Copyright 2004 - 2005, 2008 Wind River Systems, Inc. */
#include "copyright_wrs.h"
/*
modification history
--------------------
01q,25apr12,ggz Fix for WIND00346438. mRouteAdd() should add a static route
01p,19dec11,h_x Back port to 6.9.2.1 for WIND00310113
01o,29sep10,h_x Fix build and coverity warnings
01n,21jun10,h_x Fix WIND00217113
01m,02dec08,spw Fix WIND00143199
01l,03oct08,spw Fix WIND00135680
01k,31may08,spw Resolve warnings
01j,18jan08,brk ported to ipnet, moved in ifRoute* from ifLib
01i,24feb05,spm removed unneeded route format values and macros (SPR #100995)
01h,24feb05,spm performance updates and code cleanup (SPR #100995)
01g,12jan05,vvv osdep.h cleanup
01f,04oct04,niq translate unspecified protocol to the default. Fix
documentation.
01e,17sep04,niq Scale out routing sockets
01d,23aug04,rp merged from COMP_WN_IPV6_BASE6_ITER5_TO_UNIFIED_PRE_MERGE
01c,12aug04,spm fixed default route creation (SPR #99683)
01b,28may04,niq Merging from base6 label POST_ITER5_FRZ16_REBASE
01a,18feb04,rae Written
*/
/*
DESCRIPTION
This library implements a set of APIs, some of which are obsolete. This
library should only be included when necessary. All new code should use the
Routing Sockets interface.
This library contains routines for inspecting the routing table,
as well as routines for adding and deleting routes from that table.
If you do not configure VxWorks to include a routing protocol, such
as RIP or OSPF, you can use these routines to maintain the routing
tables manually.
To use this feature, include the following component:
INCLUDE_OLDROUTE
INCLUDE FILES: routeLib.h
SEE ALSO: hostLib
*/
#include <vxWorks.h>
#include <logLib.h>
#include <net/mbuf.h>
#include <sys/socket.h>
#include <sockLib.h>
#include <unistd.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <inetLib.h>
#include <errno.h>
#include <errnoLib.h>
#include <hostLib.h>
#include <stdio.h>
#include <string.h>
#include <ioLib.h>
#include "routeLib.h"
#include <m2Lib.h>
#include <taskLib.h>
#include <version.h>
#include <ipcom_sock.h>
#include <ipnet_routesock.h>
#include <ipcom_sysctl.h>
#include <ipcom_clib.h>
extern void
ipnet_cmd_init_addrs(void *msg, Ip_u32 addrs, struct Ip_sockaddr **sas);
LOCAL BOOL routeExistsOnIf(Ip_u32 addr, char *buf, BOOL exactMatch);
LOCAL BOOL routeExistsInTable(Ip_u32 addr);
/*
* The gateway address may be a struct Ip_sockaddr_dl, which we assume
* is no larger than 64 bytes.
*/
#define MAX_GW_LEN 64
#define RTM_BUFSIZE \
(sizeof(struct Ipnet_rt_msghdr) + 2 * sizeof(struct Ip_sockaddr) + MAX_GW_LEN)
#ifndef TOS_SET
#define TOS_SET(pSockaddr, tosVal) \
(((struct Ipnet_sockaddr_rt *)(pSockaddr))->srt_tos = tosVal)
#endif
#ifndef RT_PROTO_SET
#define RT_PROTO_SET(pSockaddr, proto) \
(((struct Ipnet_sockaddr_rt *)(pSockaddr))->srt_proto = proto)
#endif
#undef SAI
#define SAI(x) ((struct Ip_sockaddr_in *)(x))
#undef SA
#define SA(x) ((struct Ip_sockaddr *)(x))
/* LOCAL function */
LOCAL STATUS routeCmdExecute(int cmd, Ip_u32 dstAddr, Ip_u32 netmask,
Ip_u32 gateway, int tos, int flags, int proto,
int if_index);
/* subnet unaware version (sigh!) */
LOCAL u_long in_netof
(
struct in_addr in
)
{
register u_long net;
register u_long i = ntohl(in.s_addr);
if (IN_CLASSA(i))
net = i & IN_CLASSA_NET;
else if (IN_CLASSB(i))
net = i & IN_CLASSB_NET;
else if (IN_CLASSC(i))
net = i & IN_CLASSC_NET;
else if (IN_CLASSD(i))
net = i & IN_CLASSD_NET;
else
return (0);
return (net);
}
/*******************************************************************************
*
* oldRouteLibInit - do nothing, but ensure linkage
*
* This routine does nothing, but if called will link in this library.
*
* NOMANUAL
*
* RETURNS: nothing
*/
void oldRouteLibInit (void)
{
}
/*******************************************************************************
*
* routeAdd - add a route
*
* This routine adds gateways to the network routing tables.
* It is called from a VxWorks machine that needs
* to establish a gateway to a destination network (or machine).
*
* You can specify both <destination> and <gateway> in standard Internet
* address format (for example, 90.0.0.2), or you can specify them using
* their host names, as specified with hostAdd().
*
* This routine can be used to add multiple routes to the same destination
* differing by the gateway.
*
* EXAMPLE
* Consider the following example:
* .CS
* -> routeAdd "90.0.0.0", "gate"
* .CE
* This call tells VxWorks that the machine with the host name "gate" is
* the gateway to network 90.0.0.0. The host "gate" must already have
* been created by hostAdd().
*
* Consider the following example:
* .CS
* -> routeAdd "90.0.0.0", "91.0.0.3"
* .CE
* This call tells VxWorks that the machine with the Internet
* address 91.0.0.3 is the gateway to network 90.0.0.0.
*
* Consider the following example:
* .CS
* -> routeAdd "destination", "gate"
* .CE
* This call tells VxWorks that the machine with the host name "gate" is
* the gateway to the machine named "destination". The host names "gate" and
* "destination" must already have been created by hostAdd().
*
* Consider the following example:
* .CS
* -> routeAdd "0", "gate"
* .CE
* This call tells VxWorks that the machine with the host name "gate" is
* the default gateway. The host "gate" must already have been created
* by hostAdd(). A default gateway is where Internet Protocol (IP)
* datagrams are routed when there is no specific routing table entry
* available for the destination IP network or host.
*
* DEPRECATED
* This routine uses the old class-based addresses and does not support
* CIDR. Use mRouteAdd() or routec() instead.
*
* RETURNS: OK or ERROR.
*/
STATUS routeAdd
(
char *destination, /* inet addr or name of route destination */
char *gateway /* inet addr or name of gateway to destination */
)
{
return (routeNetAdd (destination, gateway));
}
/*******************************************************************************
*
* routeNetAdd - add a route to a destination that is a network
*
* This routine is equivalent to routeAdd(), except that the destination
* address is assumed to be a network. This is useful for adding a route
* to a sub-network that is not on the same overall network as the
* local network.
*
* This routine can be used to add multiple routes to the same destination
* differing by the gateway.
*
* DEPRECATED
* This routine uses the old class-based addresses and does not support
* CIDR. Use mRouteAdd() or routec() instead.
*
* RETURNS: OK or ERROR.
*/
STATUS routeNetAdd
(
char *destination, /* inet addr or name of network destination */
char *gateway /* inet addr or name of gateway to destination */
)
{
struct in_addr dst; /* destnation address */
struct in_addr gate; /* gateway address */
Ip_u32 dstSubnet; /* destination subnet */
Ip_u32 gateSubnet; /* gateway subnet */
Ip_u32 netmask;
Ip_u32 dstAddr;
int flags;
int tos;
int proto;
int ifIndex;
char ifName[IP_IFNAMSIZ];
int sock;
struct Ip_sockaddr_in *addrp;
Ip_u32 ifSubnet;
Ip_u32 ifAddr;
Ip_u32 ifMask;
struct Ip_ifreq ifreq;
flags = RTF_STATIC;
tos = 0;
proto = M2_ipRouteProto_other;
ifIndex = 0;
if (destination == NULL || gateway == NULL)
return (ERROR);
if (inet_aton (destination, &dst) == ERROR)
return (ERROR);
if (inet_aton (gateway, &gate) == ERROR)
return (ERROR);
/* dstSubnet and gateSubnet are in host byte order */
dstSubnet = (int)in_netof (dst);
gateSubnet = (int)in_netof (gate);
dstAddr = (int)ntohl (dst.s_addr);
/*
* If the destination is a host in the same subnet then reject the
* route. A destination is a host in the same subnet if it has the
* same subnet number as the gateway and if the destination is not
* the subnet itself (route to the subnet).
*/
if ((dstSubnet == gateSubnet) && (dstSubnet != dstAddr))
{
logMsg ("Destination %s and gateway %s are both in same subnet\n",
(_Vx_usr_arg_t)destination,
(_Vx_usr_arg_t)gateway,
(_Vx_usr_arg_t)0,
(_Vx_usr_arg_t)0,
(_Vx_usr_arg_t)0,
(_Vx_usr_arg_t)0);
return (ERROR);
}
if (inet_lnaof ((int)(dst.s_addr)) == 0) /* host portion is zero */
{
if (dstAddr == 0) /* Default route */
netmask = 0;
else if (IN_CLASSA (dstAddr))
netmask = IN_CLASSA_NET;
else if (IN_CLASSB (dstAddr))
netmask = IN_CLASSB_NET;
else if (IN_CLASSC (dstAddr))
netmask = IN_CLASSC_NET;
else if (IN_CLASSD (dstAddr))
netmask = IN_CLASSD_NET; /* XXX ??? */
else
return ERROR;
}
else /* Host route */
netmask = 0;
/* If we can reach the gateway address through one of the interfaces,
* it's possible that we'll have to do some work to add specific routes
* to the table for the interface address / subnet. Normally this
* would not be the case, as these routes are added automatically
* when and interface is brought up. However, it's possible that
* these routes can be deleted via APIs such as ifAllRoutesDelete.
* If this is the case, we need to add them back in for compatibility
* with the coreip stack.
*/
if (routeExistsOnIf(gate.s_addr, ifName, FALSE) == TRUE)
{
if ((sock = ipcom_socket (AF_INET, SOCK_RAW, 0)) < 0)
return ERROR;
strcpy(ifreq.ifr_name, ifName);
if (ipcom_socketioctl(sock, IP_SIOCGIFADDR,(char *)&ifreq) < 0)
{
ipcom_socketclose(sock);
return ERROR;
}
addrp = (struct Ip_sockaddr_in *)&ifreq.ip_ifr_addr;
ifAddr = addrp->sin_addr.s_addr;
/* Grab the netmask for this interface */
if (ipcom_socketioctl(sock, IP_SIOCGIFNETMASK,(char *)&ifreq) < 0)
{
ipcom_socketclose(sock);
return ERROR;
}
addrp = (struct Ip_sockaddr_in *)&ifreq.ip_ifr_addr;
ifMask = addrp->sin_addr.s_addr;
/* Get the subnet of this interface */
ifSubnet = gate.s_addr & ifMask;
ipcom_socketclose(sock);
/* If the interface address is not in the route table,
* add it in, passing through the loopback interface
*/
if (routeExistsInTable(ifAddr) == FALSE)
{
ifIndex = (int)ipcom_if_nametoindex("lo0");
if (ifIndex == 0)
{
ipcom_socketclose(sock);
return ERROR;
}
if (routeCmdExecute (RTM_ADD, ifAddr, 0, 0, 0,
IPNET_RTF_HOST,
M2_ipRouteProto_other, ifIndex) != OK)
{
logMsg ("Couldn't add host route through ifIndex %d.\n",
ifIndex, 0, 0, 0, 0, 0);
ipcom_socketclose(sock);
return ERROR;
}
}
else
{
ifIndex = (int)ipcom_if_nametoindex(ifName);
}
if (ifSubnet == htonl(dstSubnet))
{
ifIndex = (int)ipcom_if_nametoindex(ifName);
if (ifIndex == 0)
{
return ERROR;
}
gate.s_addr = 0;
dst.s_addr = (in_addr_t)ifSubnet;
flags = (IPNET_RTF_CLONING | IPNET_RTF_MASK);
netmask = ntohl(ifMask);
}
}
return (routeCmdExecute (RTM_ADD, dst.s_addr, htonl (netmask),
gate.s_addr, tos, flags, M2_ipRouteProto_other, ifIndex));
}
/*******************************************************************************
*
* routeDelete - delete a route
*
* This routine deletes a specified route from the network routing tables.
*
* RETURNS: OK or ERROR.
*
* DEPRECATED
* This routine uses the old class-based addresses and does not support
* CIDR. Use mRouteDelete() or routec() instead.
*
* SEE ALSO: routeAdd()
*/
STATUS routeDelete
(
char *destination, /* inet addr or name of route destination */
char *gateway /* inet addr or name of gateway to destination */
)
{
Ip_u32 destIp;
Ip_u32 gateIp;
Ip_u32 netmask;
Ip_u32 dstAddr;
int flags;
if (((destIp = (Ip_u32)inet_addr (destination)) == (Ip_u32)ERROR) ||
((gateIp = (Ip_u32)inet_addr (gateway)) == (Ip_u32)ERROR))
{
return (ERROR);
}
dstAddr = (Ip_u32)ntohl (destIp);
if (inet_lnaof (destIp) == 0) /* host portion is zero */
{
if (dstAddr == 0) /* Default route */
netmask = 0;
else if (IN_CLASSA (dstAddr))
netmask = IN_CLASSA_NET;
else if (IN_CLASSB (dstAddr))
netmask = IN_CLASSB_NET;
else if (IN_CLASSC (dstAddr))
netmask = IN_CLASSC_NET;
else if (IN_CLASSD (dstAddr))
netmask = IN_CLASSD_NET; /* XXX ??? */
else
return ERROR;
flags = 0;
}
else
{
netmask = 0;
flags = RTF_HOST;
}
flags |= RTF_STATIC;
return (routeCmdExecute (RTM_DELETE, destIp, htonl (netmask),
gateIp, 0, flags, M2_ipRouteProto_other, 0));
}
/*******************************************************************************
*
* mRouteAdd - add multiple routes to the same destination
*
* This routine is similar to routeAdd(), except that you can use multiple
* mRouteAdd() calls to add multiple routes to the same location. Use
* <pDest> to specify the destination, <pGate> to specify the gateway to
* that destination, <mask> to specify destination mask, and <tos> to specify
* the type of service. For <tos>, netinet/ip.h defines the following
* constants as valid values:
*
* IPTOS_LOWDELAY
* IPTOS_THROUGHPUT
* IPTOS_RELIABILITY
* IPTOS_MINCOST
*
* Use <flags> to specify flags you want to associate with this entry.
* Valid values for <flags> are 0, RTF_HOST and RTF_CLONING (defined in
* net/route.h).
*
* To add a host route you should specify a <mask> value of 0. <flags> can
* be set to RTF_HOST or left as zero.
*
* EXAMPLE
* To add a default route through 91.0.0.3:
* .CS
* -> mRouteAdd ("0.0.0.0", "91.0.0.3", 0, 0, 0);
* .CE
*
* To add a host route through 91.0.0.3:
* .CS
* -> mRouteAdd ("20.0.0.1", "91.0.0.3", 0, 0, 0);
* .CE
*
* To add a route to the 90.0.0.0 network through 91.0.0.3:
* .CS
* -> mRouteAdd ("90.0.0.0", "91.0.0.3", 0xffffff00, 0, 0);
* .CE
*
* Using mRouteAdd(), you could create multiple routes to the same destination.
* VxWorks would distinguish among these routes based on factors such as the
* netmask or the type of service. Thus, it is perfectly legal to say:
* .CS
* -> mRouteAdd ("90.0.0.0", "91.0.0.3", 0xffffff00, 0, 0);
*
* -> mRouteAdd ("90.0.0.0", "91.0.0.254", 0xffff0000, 0, 0);
* .CE
* This adds two routes to the same network, "90.0.0.0", that go by two
* different gateways. The differentiating factor is the netmask.
*
* This routine adds a route of type `M2_ipRouteProto_other', which is a
* static route. This route will not be modified or deleted until a
* call to mRouteDelete() removes it.
*
* RETURNS: OK or ERROR.
*
* SEE ALSO: mRouteEntryAdd(), mRouteDelete(), routeAdd()
*/
STATUS mRouteAdd
(
char * pDest, /* destination addr in internet dot notation */
char * pGate, /* gateway address in internet dot notation */
Ip_u32 mask, /* mask for destination */
int tos, /* type of service */
int flags /* route flags */
)
{
Ip_u32 destIp;
Ip_u32 gateIp;
if (((destIp = (Ip_u32)inet_addr (pDest)) == (Ip_u32)ERROR) ||
((gateIp = (Ip_u32)inet_addr (pGate)) == (Ip_u32)ERROR))
{
return (ERROR);
}
mask = htonl (mask);
flags |= RTF_STATIC;
return (mRouteEntryAdd (destIp, gateIp, mask, tos, flags,
M2_ipRouteProto_other));
}
/*******************************************************************************
*
* mRouteEntryAdd - add a protocol-specific route to the routing table
*
* For a single destination <destIp>, this routine can add additional
* routes <gateIp> to the routing table. The different routes are
* distinguished by the gateway, a destination mask <mask>,
* the type of service <tos> and associated flag values <flags>.
* Valid values for <flags> are 0, RTF_HOST, RTF_CLONING (defined in net/route.h).
* To add a host route you should specify a <mask> value of 0. <flags> can
* be set to RTF_HOST or left as zero.
*
* The <proto> parameter identifies the protocol that generated this route.
* Values for <proto> may be found in m2Lib.h. The <tos> parameter takes one of
* following values (defined in netinet/ip.h):
*
* IPTOS_LOWDELAY
* IPTOS_THROUGHPUT
* IPTOS_RELIABILITY
* IPTOS_MINCOST
*
* RETURNS: OK or ERROR.
*
* SEE ALSO: m2Lib.h, mRouteAdd(), mRouteDelete()
*/
STATUS mRouteEntryAdd
(
Ip_u32 destIp, /* destination address, network order */
Ip_u32 gateIp, /* gateway address, network order */
Ip_u32 mask, /* mask for destination, network order */
int tos, /* type of service */
int flags, /* route flags */
int proto /* routing protocol */
)
{
int rtflags;
int sock;
Ip_u32 ifIndex;
int netmask;
char ifName[IP_IFNAMSIZ];
struct Ip_sockaddr_in *addrp;
Ip_u32 ifAddr;
Ip_u32 ifSubnet;
Ip_u32 ifMask;
struct Ip_ifreq ifreq;
rtflags = flags;
netmask = (int)mask;
ifIndex = 0;
if (mask != 0)
{
/* For a host route, require a 0 mask */
if (flags & RTF_HOST)
return (ERROR);
/* Mask the destination address with the netmask */
destIp &= mask;
}
if (gateIp)
{
/* If we can reach the gateway address through one of the interfaces,
* it's possible that we'll have to do some work to add specific routes
* to the table for the interface address / subnet. Normally this
* would not be the case, as these routes are added automatically
* when and interface is brought up. However, it's possible that
* these routes can be deleted via APIs such as ifAllRoutesDelete.
* If this is the case, we need to add them back in for compatibility
* with the coreip stack.
*/
if (routeExistsOnIf(gateIp, ifName, FALSE) == TRUE)
{
if ((sock = ipcom_socket (AF_INET, SOCK_RAW, 0)) < 0)
return ERROR;
strcpy(ifreq.ifr_name, ifName);
if (ipcom_socketioctl(sock, IP_SIOCGIFADDR,(char *)&ifreq) < 0)
{
ipcom_socketclose(sock);
return ERROR;
}
addrp = (struct Ip_sockaddr_in *)&ifreq.ip_ifr_addr;
ifAddr = addrp->sin_addr.s_addr;
/* Grab the netmask for this interface */
if (ipcom_socketioctl(sock, IP_SIOCGIFNETMASK,(char *)&ifreq) < 0)
{
ipcom_socketclose(sock);
return ERROR;
}
addrp = (struct Ip_sockaddr_in *)&ifreq.ip_ifr_addr;
ifMask = addrp->sin_addr.s_addr;
/* Get the subnet of this interface */
ifSubnet = gateIp & ifMask;
ipcom_socketclose(sock);
/* If the interface address is not in the route table,
* add it in, passing through the loopback interface
*/
if (routeExistsInTable((int)ifAddr) == FALSE)
{
ifIndex = ipcom_if_nametoindex("lo0");
if (ifIndex == 0)
{
ipcom_socketclose(sock);
return ERROR;
}
if (routeCmdExecute (RTM_ADD, ifAddr, 0, 0, 0,
IPNET_RTF_HOST,
M2_ipRouteProto_other, (int)ifIndex) != OK)
{
logMsg ("Couldn't add host route through ifIndex %d.\n",
(_Vx_usr_arg_t)ifIndex,
(_Vx_usr_arg_t)0,
(_Vx_usr_arg_t)0,
(_Vx_usr_arg_t)0,
(_Vx_usr_arg_t)0,
(_Vx_usr_arg_t)0);
ipcom_socketclose(sock);
return ERROR;
}
}
if (ifSubnet == destIp)
{
ifIndex = ipcom_if_nametoindex(ifName);
if (ifIndex == 0)
{
return ERROR;
}
gateIp = 0;
destIp = ifSubnet;
rtflags = (IPNET_RTF_CLONING | IPNET_RTF_MASK);
netmask = ifMask;
}
}
}
/*
* A protocol value of 0 is not valid for route creation.
* If we do get this value, convert it to the default protocol.
* This helps support non-proto aware applications without any change.
* Note that a 0 value is valid for route deletion and specifies any
* matching route.
*/
if (proto == 0)
proto = M2_ipRouteProto_other;
return (routeCmdExecute (RTM_ADD, destIp, netmask, gateIp, tos, rtflags,
proto, ifIndex));
}
/*******************************************************************************
*
* mRouteDelete - delete a route from the routing table
*
* This routine deletes a routing table entry as specified by the
* destination, <pDest>, the destination mask, <mask>, and type of service,
* <tos>. The <tos> values are as defined in the reference entry for
* mRouteAdd().
*
* EXAMPLE
* Consider the case of a route added in the following manner:
* .CS
* -> mRouteAdd ("90.0.0.0", "91.0.0.3", 0xffffff00, 0, 0);
* .CE
* To delete a route that was added in the above manner, call mRouteDelete()
* as follows:
* .CS
* -> mRouteDelete("90.0.0.0", 0xffffff00, 0);
* .CE
*
* If the netmask and or type of service do not match, the route
* is not deleted.
*
* The valid value for <flags> is RTF_HOST for host routes or 0.
*
* To delete a host route you should specify a <mask> value of 0. <flags> can
* be set to RTF_HOST or left as zero.
*
* RETURNS: OK or ERROR.
*
* SEE ALSO: mRouteAdd()
*/
STATUS mRouteDelete
(
char * pDest, /* destination address */
Ip_u32 mask, /* mask for destination */
int tos, /* type of service */
int flags /* either 0 or RTF_HOST */
)
{
Ip_u32 destIp;
if ((destIp = (Ip_u32)inet_addr (pDest)) == (Ip_u32)ERROR)
{
return (ERROR);
}
mask = htonl (mask);
return (mRouteEntryDelete (destIp, 0, mask, tos, flags, 0));
}
/*******************************************************************************
*
* mRouteEntryDelete - delete route from the routing table
*
* This routine deletes a protocol-specific route from the routing
* table. Specify the route using a destination <pDest>, a gateway <pGate>,
* a destination mask <mask>, the type of service <tos>, a <flags> value,
* and a <proto> value that identifies the routing protocol that added the
* route. The valid values for <flags> are 0 and RTF_HOST (defined
* in net/route.h). Values for <proto> may be found in m2Lib.h and <tos>
* is one of the following values defined in netinet/ip.h:
*
* IPTOS_LOWDELAY
* IPTOS_THROUGHPUT
* IPTOS_RELIABILITY
* IPTOS_MINCOST
*
* An existing route is deleted only if it is owned by the protocol specified
* by <proto>.
*
* To delete a host route you should specify a <mask> value of 0. <flags> can
* be set to RTF_HOST or left as zero.
*
* RETURNS: OK or ERROR.
*
*/
STATUS mRouteEntryDelete
(
Ip_u32 destIp, /* destination address, network order */
Ip_u32 gateIp, /* gateway address, network order */
Ip_u32 mask, /* mask for destination, network order */
int tos, /* type of service */
int flags, /* route flags */
int proto /* routing protocol */
)
{
if (mask != 0)
{
/* For a host route, require a 0 mask */
if (flags & RTF_HOST)
return (ERROR);
/* Mask the destination address with the netmask */
destIp &= mask;
}
return (routeCmdExecute (RTM_DELETE, destIp, mask, gateIp,
tos, flags, proto, 0));
}
/*******************************************************************************
*
* routeRtmSendReply - send a routing command and wait for reply
*
* ipnet adaptation support routine
*
* RETURNS: N/A
*
* NOMANUAL
*/
LOCAL STATUS routeRtmSendReply
(
int sock,
int index,
char type,
struct Ipnet_rt_msghdr * rtm,
Ip_u32 dstAddr, /* destination address (IPv4 only) */
Ip_u32 netmask, /* IPv4 prefix length */
struct Ip_sockaddr * gw, /* gateway address */
int flags /* route flags */
)
{
int seq;
struct Ip_sockaddr_in *net;
struct Ip_sockaddr_in *mask;
struct Ip_sockaddr_in *gate;
struct Ip_sockaddr_in *gwp;
int sa_len;
int err;
ssize_t size = sizeof(struct Ipnet_rt_msghdr);
IP_TASK_ID pid = taskIdSelf();
seq = (int)ipcom_random();
ipcom_memset (rtm, 0, RTM_BUFSIZE);
rtm->rtm_version = (Ip_u16)IPNET_RTM_VERSION;
rtm->rtm_msglen = (Ip_u16)size;
rtm->rtm_type = type;
rtm->rtm_pid = (Ip_pid_t)pid;
rtm->rtm_seq = seq;
rtm->rtm_index = index;
rtm->rtm_flags = flags;
net = (struct Ip_sockaddr_in *) (rtm + 1);
net->sin_len = sizeof (struct sockaddr_in);
rtm->rtm_msglen = (Ip_u16)(rtm->rtm_msglen + (net->sin_len));
net->sin_family = AF_INET;
net->sin_addr.s_addr = dstAddr;
rtm->rtm_addrs |= IPNET_RTA_DST;
gate = (struct Ip_sockaddr_in *) (net + 1);
gwp = (struct Ip_sockaddr_in *)gw;
if (gwp != NULL && gwp->sin_addr.s_addr)
{
sa_len = (int)(gw->sa_len ? IP_ROUNDUP(gw->sa_len, sizeof(Ip_u32))
: sizeof(Ip_u32));
if (sa_len > MAX_GW_LEN)
{
errnoSet (EINVAL);
return ERROR;
}
ipcom_memcpy(gate, gw, (size_t)sa_len);
rtm->rtm_msglen = (Ip_u16)(rtm->rtm_msglen + sa_len);
rtm->rtm_addrs |= IPNET_RTA_GATEWAY;
mask = (struct Ip_sockaddr_in *) ((char *)gate + sa_len);
}
else
mask = gate;
if (type == RTM_ADD)
{
rtm->rtm_flags |= IPNET_RTF_UP | IPNET_RTF_DONE;
rtm->rtm_rmx.rmx_expire = IPCOM_ADDR_INFINITE;
if ( dstAddr && netmask == 0)
{
rtm->rtm_flags |= RTF_HOST;
}
else if (gwp != NULL && gwp->sin_addr.s_addr)
{
rtm->rtm_flags |= IPNET_RTF_GATEWAY;
}
}
if ( ! (rtm->rtm_flags & RTF_HOST))
{
mask->sin_len = sizeof (struct sockaddr_in);
rtm->rtm_msglen = (Ip_u16)(rtm->rtm_msglen + mask->sin_len);
mask->sin_family = AF_INET;
mask->sin_addr.s_addr = netmask;
rtm->rtm_addrs |= IPNET_RTA_NETMASK;
}
err = (int)ipcom_send(sock, (const char *)rtm, rtm->rtm_msglen, 0);
if (err < 0)
{
return ERROR;
}
do
{
size = ipcom_recv(sock, (char *)rtm, (Ip_size_t)(RTM_BUFSIZE), MSG_DONTWAIT);
if (size < 0)
{
return ERROR;
}
}
while (rtm->rtm_type != type || rtm->rtm_seq != seq || rtm->rtm_pid != (Ip_pid_t)pid);
if (rtm->rtm_errno != 0)
{
return ERROR;
}
return OK;
}
/*******************************************************************************
*
* routeCmdExecute - execute the specified routing command
*
* The <msgtype> parameter corresponds to the routing operation to
* perform. The value of RTM_ADD (1) creates a route, and RTM_DELETE (2)
* deletes an existing route. The <dstAddr> parameter specifies the
* IPv4 destination address for the route.
*
* The <gateway> parameter usually must specify a valid gateway address
* directly reachable through a network interface.
*
* The <netmask> parameter contains the netmask for the new (or
* existing) route's netmask. A netmask value of 0 signifies a host route
* unless <dstAddr> is also zero, which specifies a default route.
*
* All the addresses are specified in network byte order
*
* The routeCmdExecute() routine calls the underlying routing API to
* perform the specified operation.
*
* RETURNS: OK or ERROR.
*
* NOMANUAL
*/
LOCAL STATUS routeCmdExecute
(
int cmd, /* routing operation */
Ip_u32 dstAddr, /* destination address (IPv4 only) */
Ip_u32 netmask, /* IPv4 prefix length */
Ip_u32 gateway, /* gateway address (IPv4 only) */
int tos, /* type of service * ignored * */
int flags, /* route flags */
int proto, /* routing protocol * ignored * */
int if_index
)
{
int sock, status;
struct Ipnet_rt_msghdr * rtm;
struct Ip_sockaddr_in gw;
if ((sock = ipcom_socket(AF_ROUTE, SOCK_RAW, 0)) < 0)
return (ERROR);
rtm = (struct Ipnet_rt_msghdr *)ipcom_malloc(RTM_BUFSIZE);
if (rtm == IP_NULL)
{
ipcom_socketclose (sock);
return ERROR;
}
ipcom_memset (&gw, 0, sizeof (gw));
gw.sin_family = AF_INET;
gw.sin_len = sizeof (gw);
gw.sin_addr.s_addr = (Ip_u32)gateway;
status = routeRtmSendReply(sock, if_index, (char)cmd, rtm, dstAddr,
netmask, SA(&gw), flags);
ipcom_socketclose(sock);
ipcom_free(rtm);
return status;
}
/*******************************************************************************
*
* routeExistsOnIf- Determine whether the address exists on an enabled interface
*
* The <addr> parameter corresponds to an address to check.
* The <buf> parameter corresponds to a pointer to a pre-allocated buffer of
* minimum size IP_IFNAMSIZ
* The <exactMatch> parameter determines whether the <addr> is a host route
* through the interface. That is, <exactMatch> is TRUE, whetherthe addr
* exists as a primary address on one of the interfaces.
*
* If the address exists on an 'UP' interface, TRUE is returned and the
* interface name is copied into the supplied buffer. Otherwise, FALSE
* is returned.
*
* RETURNS: OK or ERROR.
*
* NOMANUAL
*/
LOCAL BOOL routeExistsOnIf(Ip_u32 addr, char *ifNameBuffer, BOOL exactMatch)
{
struct Ip_if_nameindex *oifrs, *ifrs;
struct Ip_ifreq ifreq;
struct Ip_sockaddr_in *addrp;
int sock;
int ret = FALSE;
Ip_u32 ifAddr;
Ip_u32 ifMask;
Ip_u32 ifSubnet;
Ip_u32 addrSubnet;
/* Socket to use with interface ioctl */
if ((sock = ipcom_socket (AF_INET, SOCK_RAW, 0)) < 0)
return FALSE;
/* Search through all of the interfaces */
ifrs = ipcom_if_nameindex();
if (ifrs == IP_NULL || strlen(ifrs->if_name) >= IP_IFNAMSIZ)
{
ipcom_if_freenameindex(ifrs);
ipcom_socketclose(sock);
return FALSE;
}
for (oifrs = ifrs; ifrs && ifrs->if_name != IP_NULL; ifrs++)
{
/* Check if interface is up. */
strcpy(ifreq.ifr_name, ifrs->if_name);
if (ipcom_socketioctl(sock, IP_SIOCGIFFLAGS,(char *)&ifreq) < 0)
{
continue;
}
if (IP_BIT_ISFALSE(ifreq.ifr_ifru.ifru_flags, IP_IFF_UP))
continue;
/* Grab the primary address on this interface */
if (ipcom_socketioctl(sock, IP_SIOCGIFADDR,(char *)&ifreq) < 0)
{
continue;
}
addrp = (struct Ip_sockaddr_in *)&ifreq.ip_ifr_addr;
ifAddr = addrp->sin_addr.s_addr;
/* Grab the netmask for this interface */
if (ipcom_socketioctl(sock, IP_SIOCGIFNETMASK,(char *)&ifreq) < 0)
{
ipcom_socketclose(sock);
return ERROR;
}
addrp = (struct Ip_sockaddr_in *)&ifreq.ip_ifr_addr;
ifMask = addrp->sin_addr.s_addr;
ifSubnet = ifAddr & ifMask;
addrSubnet = addr & ifMask;
/* Check the match */
if (exactMatch == TRUE)
{
if (addr == ifAddr)
{
ret = TRUE;
strncpy(ifNameBuffer, ifrs->if_name, IP_IFNAMSIZ);
}
}
else
{
if (ifSubnet == addrSubnet)
{
ret = TRUE;
strncpy(ifNameBuffer, ifrs->if_name, IP_IFNAMSIZ);
}
}
}
ipcom_if_freenameindex(oifrs);
ipcom_socketclose(sock);
return ret;
}
/*******************************************************************************
*
* routeExistsInTable - Determine whether the address exists in the routing
* table
*
* The <addr> parameter corresponds to an route to check. If the address
* exists in the routing table, TRUE is returned. Otherwise, FALSE is returned.
*
* RETURNS: OK or ERROR.
*
* NOMANUAL
*/
LOCAL BOOL routeExistsInTable(Ip_u32 addr)
{
int sock;
int status;
int flags;
int ret;
struct Ipnet_rt_msghdr * rtm;
flags = RTF_STATIC | RTF_UP | RTF_HOST | RTF_GATEWAY;
ret = FALSE;
if ((sock = ipcom_socket(AF_ROUTE, SOCK_RAW, 0)) < 0)
return (ERROR);
rtm = (struct Ipnet_rt_msghdr *)ipcom_malloc(RTM_BUFSIZE);
if (rtm == IP_NULL)
{
ipcom_socketclose (sock);
return ERROR;
}
status = routeRtmSendReply(sock, 0, RTM_GET, rtm, (ULONG)addr, 0, 0, flags);
if (status != ERROR && rtm->rtm_errno == 0)
{
ret = TRUE;
}
ipcom_socketclose (sock);
ipcom_free(rtm);
return ret;
}