1 
2 #include "protoRouteMgr.h"
3 #include "protoDebug.h"
4 
5 #include <Iphlpapi.h>
6 #include <Iprtrmib.h>
7 #define MPR50 1
8 #ifndef _WIN32_WCE
9 #include <Routprot.h>
10 #endif // !_WIN32_WCE
11 
12 class Win32RouteMgr : public ProtoRouteMgr
13 {
14     public:
15         Win32RouteMgr();
16         ~Win32RouteMgr();
17 
18         virtual bool Open(const void* userData = NULL);
IsOpen() const19         virtual bool IsOpen() const {return true;}
20         virtual void Close();
21 
22         virtual bool GetAllRoutes(ProtoAddress::Type addrType,
23                                   ProtoRouteTable&   routeTable);
24 
25         virtual bool GetRoute(const ProtoAddress& dst,
26                               unsigned int        prefixLen,
27                               ProtoAddress&       gw,
28                               unsigned int&       ifIndex,
29                               int&                metric);
30 
31         virtual bool SetRoute(const ProtoAddress& dst,
32                               unsigned int        prefixLen,
33                               const ProtoAddress& gw,
34                               unsigned int        ifIndex,
35                               int                 metric);
36 
37         virtual bool DeleteRoute(const ProtoAddress& dst,
38                                  unsigned int        prefixLen,
39                                  const ProtoAddress& gw,
40                                  unsigned int        ifIndex);
41 
42         virtual bool SetForwarding(bool state);
43 
44         // Network interface helper functions
GetInterfaceIndex(const char * interfaceName)45         virtual unsigned int GetInterfaceIndex(const char* interfaceName)
46         {
47             return ProtoSocket::GetInterfaceIndex(interfaceName);
48         }
GetInterfaceAddressList(unsigned int ifIndex,ProtoAddress::Type addrType,ProtoAddressList & addrList)49         virtual bool GetInterfaceAddressList(unsigned int        ifIndex,
50                                              ProtoAddress::Type  addrType,
51                                              ProtoAddressList&   addrList)
52         {
53             char ifName[256];
54             bool result = ProtoSocket::GetInterfaceName(ifIndex, ifName, 255);
55             return result ? ProtoSocket::GetInterfaceAddressList(ifName, addrType, addrList) : false;
56         }
GetInterfaceName(unsigned int ifIndex,char * buffer,unsigned int buflen)57         virtual bool GetInterfaceName(unsigned int  ifIndex,
58                                       char*         buffer,
59                                       unsigned int  buflen)
60         {
61             return ProtoSocket::GetInterfaceName(ifIndex, buffer, buflen);
62         }
63 
64     private:
65 
66 
67 };  // end class Win32RouteMgr
68 
Create(Type)69 ProtoRouteMgr* ProtoRouteMgr::Create(Type /*type*/)
70 {
71     // TBD - support alternative route mgr "types" (e.g. ZEBRA)
72     return static_cast<ProtoRouteMgr*>(new Win32RouteMgr);
73 }
74 
Win32RouteMgr()75 Win32RouteMgr::Win32RouteMgr()
76 {
77 }
78 
~Win32RouteMgr()79 Win32RouteMgr::~Win32RouteMgr()
80 {
81 }
82 
Open(const void *)83 bool Win32RouteMgr::Open(const void* /*userData*/)
84 {
85     return true;
86 
87 }  // end Win32RouteMgr::Open()
88 
Close()89 void Win32RouteMgr::Close()
90 {
91 
92 }  // end Win32RouteMgr::Close()
93 
94 
SetForwarding(bool state)95 bool Win32RouteMgr::SetForwarding(bool state)
96 {
97     MIB_IPSTATS ipStats;
98 
99     ipStats.dwDefaultTTL = MIB_USE_CURRENT_TTL;
100     ipStats.dwForwarding = state ? MIB_IP_FORWARDING : MIB_IP_NOT_FORWARDING;
101     if (NO_ERROR == SetIpStatistics(&ipStats))
102     {
103         return true;
104     }
105     else
106     {
107         PLOG(PL_ERROR, "Win32RouteMgr::SetForwarding() SetIpStatistics() error: %s\n", GetErrorString());
108         return false;
109     }
110 }  // end Win32RouteMgr::SetForwarding()
111 
GetRoute(const ProtoAddress & dst,unsigned int prefixLen,ProtoAddress & gw,unsigned int & ifIndex,int & metric)112 bool Win32RouteMgr::GetRoute(const ProtoAddress& dst,
113                              unsigned int        prefixLen,
114                              ProtoAddress&       gw,
115                              unsigned int&       ifIndex,
116                              int&                metric)
117 {
118     ProtoRouteTable routeTable;
119 
120     if (!GetAllRoutes(dst.GetType(), routeTable))
121     {
122         PLOG(PL_ERROR, "Win32RouteMgr::GetRoute() error getting system route table\n");
123         return false;
124     }
125     return routeTable.FindRoute(dst, prefixLen, gw, ifIndex, metric);
126 }  // end Win32RouteMgr::GetRoute()
127 
SetRoute(const ProtoAddress & dst,unsigned int prefixLen,const ProtoAddress & gw,unsigned int ifIndex,int metric)128 bool Win32RouteMgr::SetRoute(const ProtoAddress& dst,
129                              unsigned int        prefixLen,
130                              const ProtoAddress& gw,
131                              unsigned int        ifIndex,
132                              int                 metric)
133 {
134     if (ProtoAddress::IPv4 != dst.GetType())
135     {
136         PLOG(PL_ERROR, "Win32RouteMgr::SetRoute() error: IPv6 not yet supported\n");
137         return false;
138     }
139     if (0 == ifIndex)
140     {
141         PLOG(PL_ERROR, "Win32RouteMgr::SetRoute() error: ifIndex not specified!\n");
142         return false;
143     }
144 	int oldmetric = 0;
145 	ProtoAddress oldgw;
146 	if(GetRoute(dst,prefixLen,oldgw,ifIndex,oldmetric))
147 		DeleteRoute(dst,prefixLen,oldgw,ifIndex);
148 	MIB_IPFORWARDROW entry;
149     memset(&entry, 0, sizeof(MIB_IPFORWARDROW));
150 	entry.dwForwardDest = htonl(dst.IPv4GetAddress());
151     ProtoAddress mask;
152     mask.Reset(dst.GetType(), false);
153     mask.ApplyPrefixMask(prefixLen);
154 	entry.dwForwardMask = htonl(mask.IPv4GetAddress());
155     if (gw.IsValid())
156         entry.dwForwardNextHop = htonl(gw.IPv4GetAddress());
157     else
158         entry.dwForwardNextHop = htonl(dst.IPv4GetAddress());
159 	entry.dwForwardIfIndex = ifIndex;
160  	entry.dwForwardProto = PROTO_IP_NETMGMT;
161 
162     // First, attempt to set as an existing entry
163     if (NO_ERROR != SetIpForwardEntry(&entry))
164     {
165         if (NO_ERROR != CreateIpForwardEntry(&entry))
166         {
167             PLOG(PL_ERROR, "Win32RouteMgr::SetRoute() CreateIpForwardEntry() error\n");
168             return false;
169         }
170         else
171         {
172             return true;
173         }
174     }
175     else
176     {
177         return true;
178     }
179 }  // end Win32RouteMgr::SetRoute()
180 
DeleteRoute(const ProtoAddress & dst,unsigned int prefixLen,const ProtoAddress & gw,unsigned int ifIndex)181 bool Win32RouteMgr::DeleteRoute(const ProtoAddress& dst,
182                                 unsigned int        prefixLen,
183                                 const ProtoAddress& gw,
184                                 unsigned int        ifIndex)
185 {
186     if (ProtoAddress::IPv4 != dst.GetType())
187     {
188         PLOG(PL_ERROR, "Win32RouteMgr::DeleteRoute() error: IPv6 not yet supported\n");
189         return false;
190     }
191     if (0 == ifIndex)
192     {
193         PLOG(PL_ERROR, "Win32RouteMgr::DeleteRoute() error: ifIndex not specified!\n");
194         return false;
195     }
196 	MIB_IPFORWARDROW entry;
197     memset(&entry, 0, sizeof(MIB_IPFORWARDROW));
198 	entry.dwForwardDest = htonl(dst.IPv4GetAddress());
199     ProtoAddress mask;
200     mask.Reset(dst.GetType(), false);
201     mask.ApplyPrefixMask(prefixLen);
202 	entry.dwForwardMask = htonl(mask.IPv4GetAddress());
203     if (gw.IsValid())
204     {
205 	    entry.dwForwardNextHop = htonl(gw.IPv4GetAddress());
206     }
207     else
208     {
209 		entry.dwForwardNextHop = htonl(dst.IPv4GetAddress());
210 	}
211 	entry.dwForwardIfIndex = ifIndex;
212  	entry.dwForwardProto = PROTO_IP_NETMGMT;
213 
214 	if (NO_ERROR != DeleteIpForwardEntry(&entry))
215     {
216         PLOG(PL_ERROR, "Win32RouteMgr::DeleteRoute() DeleteIpForwardEntry() error\n");
217         return false;
218     }
219     else
220     {
221         return true;
222     }
223 }  // end Win32RouteMgr::DeleteRoute()
224 
225 
GetAllRoutes(ProtoAddress::Type addrType,ProtoRouteTable & routeTable)226 bool Win32RouteMgr::GetAllRoutes(ProtoAddress::Type addrType,
227                                  ProtoRouteTable&   routeTable)
228 {
229     unsigned long bufferSize = 0;
230     GetIpForwardTable((MIB_IPFORWARDTABLE*)NULL, &bufferSize, FALSE);
231     char* buffer = new char[bufferSize];
232     if (NULL == buffer)
233     {
234         PLOG(PL_ERROR, "Win32RouteMgr::GetAllRoutes() new buffer[%lu] error\n", bufferSize);
235         return false;
236     }
237     MIB_IPFORWARDTABLE* fwdTable = (MIB_IPFORWARDTABLE*)buffer;
238     if (NO_ERROR != GetIpForwardTable(fwdTable, &bufferSize, FALSE))
239     {
240         PLOG(PL_ERROR, "Win32RouteMgr::GetAllRoutes() new MIB_IPFORWARDTABLE error\n");
241         delete[] buffer;
242         return false;
243     }
244     bool result = true;
245     DWORD numEntries = fwdTable->dwNumEntries;
246     for (DWORD i = 0 ; i < numEntries; i++)
247     {
248         MIB_IPFORWARDROW& entry = fwdTable->table[i];
249         ProtoAddress destination;
250         destination.SetRawHostAddress(ProtoAddress::IPv4, (char*)&entry.dwForwardDest, sizeof(DWORD));
251         ProtoAddress gateway;
252         gateway.SetRawHostAddress(ProtoAddress::IPv4, (char*)&entry.dwForwardNextHop, sizeof(DWORD));
253         ProtoAddress mask;
254         mask.SetRawHostAddress(ProtoAddress::IPv4, (char*)&entry.dwForwardMask, sizeof(DWORD));
255         unsigned int prefixLen = mask.GetPrefixLength();
256         if (!routeTable.SetRoute(destination, prefixLen, gateway, entry.dwForwardIfIndex, entry.dwForwardMetric1))
257         {
258             PLOG(PL_ERROR, "Win32RouteMgr::GetAllRoutes() error creating table entry\n");
259             result = false;
260             break;
261         }
262     }
263     delete[] buffer;
264     return result;
265 }  // end Win32RouteMgr::GetAllRoutes()
266