Create a branch for network fixes.
[reactos.git] / base / applications / network / route / route.c
1 /* Poor man's route
2 *
3 * Supported commands:
4 *
5 * "print"
6 * "add" target ["mask" mask] gw ["metric" metric]
7 * "delete" target gw
8 *
9 * Goals:
10 *
11 * Flexible, simple
12 */
13
14 #include <stdio.h>
15 #include <winsock2.h>
16 #include <windows.h>
17 #include <iphlpapi.h>
18 #include <tchar.h>
19
20 #define IPBUF 17
21 #define IN_ADDR_OF(x) *((struct in_addr *)&(x))
22
23 static int Usage()
24 {
25 _ftprintf( stderr,
26 _T("route usage:\n")
27 _T("route print\n")
28 _T(" prints the route table\n")
29 _T("route add <target> [mask <mask>] <gw> [metric <m>]\n")
30 _T(" adds a route\n")
31 _T("route delete <target> <gw>\n")
32 _T(" deletes a route\n") );
33 return 1;
34 }
35
36 static int PrintRoutes()
37 {
38 PMIB_IPFORWARDTABLE IpForwardTable = NULL;
39 PIP_ADAPTER_INFO pAdapterInfo;
40 ULONG Size = 0;
41 DWORD Error = 0;
42 ULONG adaptOutBufLen = sizeof(IP_ADAPTER_INFO);
43 TCHAR DefGate[16];
44 TCHAR Destination[IPBUF], Gateway[IPBUF], Netmask[IPBUF];
45 unsigned int i;
46
47 /* set required buffer size */
48 pAdapterInfo = (IP_ADAPTER_INFO *) malloc( adaptOutBufLen );
49 if (pAdapterInfo == NULL)
50 {
51 Error = ERROR_NOT_ENOUGH_MEMORY;
52 goto Error;
53 }
54 if (GetAdaptersInfo( pAdapterInfo, &adaptOutBufLen) == ERROR_BUFFER_OVERFLOW)
55 {
56 free (pAdapterInfo);
57 pAdapterInfo = (IP_ADAPTER_INFO *) malloc (adaptOutBufLen);
58 if (pAdapterInfo == NULL)
59 {
60 Error = ERROR_NOT_ENOUGH_MEMORY;
61 goto Error;
62 }
63 }
64
65 if( (GetIpForwardTable( NULL, &Size, TRUE )) == ERROR_INSUFFICIENT_BUFFER )
66 {
67 if (!(IpForwardTable = malloc( Size )))
68 {
69 free(pAdapterInfo);
70 Error = ERROR_NOT_ENOUGH_MEMORY;
71 goto Error;
72 }
73 }
74
75 if (((Error = GetAdaptersInfo(pAdapterInfo, &adaptOutBufLen)) == NO_ERROR) &&
76 ((Error = GetIpForwardTable(IpForwardTable, &Size, TRUE)) == NO_ERROR))
77 {
78 _stprintf(DefGate,
79 #ifdef UNICODE
80 _T("%hs"),
81 #else
82 _T("%s"),
83 #endif
84 pAdapterInfo->GatewayList.IpAddress.String);
85 _tprintf(_T("===========================================================================\n"));
86 _tprintf(_T("Interface List\n"));
87 /* FIXME - sort by the index! */
88 while (pAdapterInfo)
89 {
90 #ifdef UNICODE
91 _tprintf(_T("0x%lu ........................... %hs\n"),
92 #else
93 _tprintf(_T("0x%lu ........................... %s\n"),
94 #endif
95 pAdapterInfo->Index, pAdapterInfo->Description);
96 pAdapterInfo = pAdapterInfo->Next;
97 }
98 _tprintf(_T("===========================================================================\n"));
99
100 _tprintf(_T("===========================================================================\n"));
101 _tprintf(_T("Active Routes:\n"));
102 _tprintf( _T("%-27s%-17s%-14s%-11s%-10s\n"),
103 _T("Network Destination"),
104 _T("Netmask"),
105 _T("Gateway"),
106 _T("Interface"),
107 _T("Metric") );
108 for( i = 0; i < IpForwardTable->dwNumEntries; i++ )
109 {
110 _stprintf( Destination,
111 #ifdef UNICODE
112 _T("%hs"),
113 #else
114 _T("%s"),
115 #endif
116 inet_ntoa( IN_ADDR_OF(IpForwardTable->table[i].dwForwardDest) ) );
117 _stprintf( Netmask,
118 #ifdef UNICODE
119 _T("%hs"),
120 #else
121 _T("%s"),
122 #endif
123 inet_ntoa( IN_ADDR_OF(IpForwardTable->table[i].dwForwardMask) ) );
124 _stprintf( Gateway,
125 #ifdef UNICODE
126 _T("%hs"),
127 #else
128 _T("%s"),
129 #endif
130 inet_ntoa( IN_ADDR_OF(IpForwardTable->table[i].dwForwardNextHop) ) );
131
132 _tprintf( _T("%17s%17s%17s%16ld%9ld\n"),
133 Destination,
134 Netmask,
135 Gateway,
136 IpForwardTable->table[i].dwForwardIfIndex,
137 IpForwardTable->table[i].dwForwardMetric1 );
138 }
139 _tprintf(_T("Default Gateway:%18s\n"), DefGate);
140 _tprintf(_T("===========================================================================\n"));
141 _tprintf(_T("Persistent Routes:\n"));
142
143 free(IpForwardTable);
144 free(pAdapterInfo);
145
146 return ERROR_SUCCESS;
147 }
148 else
149 {
150 Error:
151 _ftprintf( stderr, _T("Route enumerate failed\n") );
152 return Error;
153 }
154 }
155
156 static int convert_add_cmd_line( PMIB_IPFORWARDROW RowToAdd,
157 int argc, TCHAR **argv ) {
158 int i;
159 #ifdef UNICODE
160 char addr[16];
161 #endif
162
163 if( argc > 1 )
164 {
165 #ifdef UNICODE
166 sprintf( addr, "%ls", argv[0] );
167 RowToAdd->dwForwardDest = inet_addr( addr );
168 #else
169 RowToAdd->dwForwardDest = inet_addr( argv[0] );
170 #endif
171 }
172 else
173 return FALSE;
174 for( i = 1; i < argc; i++ )
175 {
176 if( !_tcscmp( argv[i], _T("mask") ) )
177 {
178 i++; if( i >= argc ) return FALSE;
179 #ifdef UNICODE
180 sprintf( addr, "%ls", argv[i] );
181 RowToAdd->dwForwardMask = inet_addr( addr );
182 #else
183 RowToAdd->dwForwardMask = inet_addr( argv[i] );
184 #endif
185 }
186 else if( !_tcscmp( argv[i], _T("metric") ) )
187 {
188 i++;
189 if( i >= argc )
190 return FALSE;
191 RowToAdd->dwForwardMetric1 = _ttoi( argv[i] );
192 }
193 else
194 {
195 #ifdef UNICODE
196 sprintf( addr, "%ls", argv[i] );
197 RowToAdd->dwForwardNextHop = inet_addr( addr );
198 #else
199 RowToAdd->dwForwardNextHop = inet_addr( argv[i] );
200 #endif
201 }
202 }
203
204 return TRUE;
205 }
206
207 static int add_route( int argc, TCHAR **argv ) {
208 MIB_IPFORWARDROW RowToAdd = { 0 };
209 DWORD Error;
210
211 if( argc < 2 || !convert_add_cmd_line( &RowToAdd, argc, argv ) )
212 {
213 _ftprintf( stderr,
214 _T("route add usage:\n")
215 _T("route add <target> [mask <mask>] <gw> [metric <m>]\n")
216 _T(" Adds a route to the IP route table.\n")
217 _T(" <target> is the network or host to add a route to.\n")
218 _T(" <mask> is the netmask to use (autodetected if unspecified)\n")
219 _T(" <gw> is the gateway to use to access the network\n")
220 _T(" <m> is the metric to use (lower is preferred)\n") );
221 return 1;
222 }
223
224 if( (Error = CreateIpForwardEntry( &RowToAdd )) == ERROR_SUCCESS )
225 return 0;
226
227 _ftprintf( stderr, _T("Route addition failed\n") );
228 return Error;
229 }
230
231 static int del_route( int argc, TCHAR **argv )
232 {
233 MIB_IPFORWARDROW RowToDel = { 0 };
234 DWORD Error;
235
236 if( argc < 2 || !convert_add_cmd_line( &RowToDel, argc, argv ) )
237 {
238 _ftprintf( stderr,
239 _T("route delete usage:\n")
240 _T("route delete <target> <gw>\n")
241 _T(" Removes a route from the IP route table.\n")
242 _T(" <target> is the network or host to add a route to.\n")
243 _T(" <gw> is the gateway to remove the route from.\n") );
244 return 1;
245 }
246
247 if( (Error = DeleteIpForwardEntry( &RowToDel )) == ERROR_SUCCESS )
248 return 0;
249
250 _ftprintf( stderr, _T("Route addition failed\n") );
251 return Error;
252 }
253
254 int _tmain( int argc, TCHAR **argv )
255 {
256 if( argc < 2 )
257 return Usage();
258 else if ( !_tcscmp( argv[1], _T("print") ) )
259 return PrintRoutes();
260 else if( !_tcscmp( argv[1], _T("add") ) )
261 return add_route( argc-2, argv+2 );
262 else if( !_tcscmp( argv[1], _T("delete") ) )
263 return del_route( argc-2, argv+2 );
264 else
265 return Usage();
266 }