1 ////////////////////////////////////////////////////////////////////////////////////
2 // w32ctca.c CTCI-W32 (Channel to Channel link to Win32 TCP/IP stack)
3 ////////////////////////////////////////////////////////////////////////////////////
4 // (c) Copyright "Fish" (David B. Trout), 2002-2009. Released under the Q Public License
5 // (http://www.hercules-390.org/herclic.html) as modifications to Hercules.
6 ////////////////////////////////////////////////////////////////////////////////////
7
8 #include "hstdinc.h"
9 #include "hercules.h"
10
11 #if !defined(OPTION_W32_CTCI)
12 int w32ctca_dummy = 0;
13 #else // defined(OPTION_W32_CTCI)
14
15 #include "w32ctca.h"
16 #include "tt32api.h" // (exported TunTap32.dll functions)
17 #ifdef __CYGWIN__
18 #include <sys/cygwin.h> // (for cygwin_conv_to_full_win32_path)
19 #endif
20
21 ///////////////////////////////////////////////////////////////////////////////////////////
22 // We prefer the '_ex' variety as they resolve the "no error" errno issue...
23 // But if they're not available we'll settle for the older version...
24
25 #define TT32_PROCADDRS( name ) \
26 \
27 ptuntap32_ ## name ## _ex g_tt32_pfn_ ## name ## _ex = NULL; \
28 ptuntap32_ ## name g_tt32_pfn_ ## name = NULL
29
30 #define GET_TT32_PROCADDRS( name ) \
31 \
32 g_tt32_pfn_ ## name ## _ex = \
33 (ptuntap32_ ## name ## _ex ) GetProcAddress( g_tt32_hmoddll, \
34 "tuntap32_" # name "_ex" ); \
35 g_tt32_pfn_ ## name = \
36 (ptuntap32_ ## name ) GetProcAddress( g_tt32_hmoddll, \
37 "tuntap32_" # name ); if (! \
38 g_tt32_pfn_ ## name ) goto error
39
40 ///////////////////////////////////////////////////////////////////////////////////////////
41 // Global variables...
42
43 #define TT32_DEFAULT_IFACE "00-00-5E-80-00-00"
44
45 CRITICAL_SECTION g_tt32_lock; // (lock for accessing ALL below variables)
46
47 char g_tt32_dllname [ MAX_TT32_DLLNAMELEN ] = {0};
48 HMODULE g_tt32_hmoddll = NULL;
49
50 TT32_PROCADDRS ( open );
51 TT32_PROCADDRS ( close );
52 TT32_PROCADDRS ( read );
53 TT32_PROCADDRS ( write );
54 TT32_PROCADDRS ( ioctl );
55 TT32_PROCADDRS ( get_stats );
56 TT32_PROCADDRS ( get_default_iface );
57 TT32_PROCADDRS ( set_debug_output_func );
58 TT32_PROCADDRS ( version_string );
59 TT32_PROCADDRS ( version_numbers );
60 TT32_PROCADDRS ( copyright_string );
61
62 // (NOTE: the following function only exists in v3.0+)
63
64 ptuntap32_build_herc_iface_mac g_tt32_pfn_build_herc_iface_mac = NULL;
65
66 ///////////////////////////////////////////////////////////////////////////////////////////
67
GetTT32ProcAddrs()68 BOOL GetTT32ProcAddrs()
69 {
70 GET_TT32_PROCADDRS ( open );
71 GET_TT32_PROCADDRS ( close );
72 GET_TT32_PROCADDRS ( read );
73 GET_TT32_PROCADDRS ( write );
74 GET_TT32_PROCADDRS ( ioctl );
75 GET_TT32_PROCADDRS ( get_stats );
76 GET_TT32_PROCADDRS ( get_default_iface );
77 GET_TT32_PROCADDRS ( set_debug_output_func );
78 GET_TT32_PROCADDRS ( version_string );
79 GET_TT32_PROCADDRS ( version_numbers );
80 GET_TT32_PROCADDRS ( copyright_string );
81
82 // (NOTE: we don't NEED this function (since it's new to
83 // v3.0+ of tuntap32) so it's okay if it doesn't exist)
84
85 g_tt32_pfn_build_herc_iface_mac =
86 (ptuntap32_build_herc_iface_mac ) GetProcAddress( g_tt32_hmoddll,
87 "tuntap32_build_herc_iface_mac" );
88
89 LeaveCriticalSection(&g_tt32_lock);
90 return TRUE;
91
92 error:
93
94 FreeLibrary( g_tt32_hmoddll );
95 g_tt32_hmoddll = NULL;
96 logmsg( "** tt32_loaddll: One of the GetProcAddress calls failed\n" );
97 LeaveCriticalSection(&g_tt32_lock);
98 return FALSE;
99 }
100
101 ///////////////////////////////////////////////////////////////////////////////////////////
102 // Debug string output function for use by the TUNTAP32.DLL...
103
tt32_output_debug_string(const char * debug_string)104 void __cdecl tt32_output_debug_string( const char* debug_string )
105 {
106 logmsg( "%s", debug_string );
107 }
108
enable_tt32_debug_tracing(int enable)109 void enable_tt32_debug_tracing( int enable )
110 {
111 // Pass to TunTap32 DLL a pointer to the function it can use to
112 // display debug messages with. This function of our's (that we
113 // are passing it a pointer to) will then display its debugging
114 // message (string) on the Hercules console so we can see it.
115
116 g_tt32_pfn_set_debug_output_func( enable ? &tt32_output_debug_string : NULL );
117 }
118
119 ///////////////////////////////////////////////////////////////////////////////////////////
120 // Load the TUNTAP32.DLL...
121
tt32_loaddll()122 BOOL tt32_loaddll()
123 {
124 char* pszDLLName;
125 char tt32_dllname_in_buff [ MAX_PATH ];
126 char tt32_dllname_out_buff [ MAX_PATH ] = {0};
127 static int tt32_init_done = 0;
128
129 if (!tt32_init_done)
130 {
131 InitializeCriticalSection( &g_tt32_lock );
132 tt32_init_done = 1;
133 }
134
135 EnterCriticalSection(&g_tt32_lock);
136
137 if (g_tt32_hmoddll)
138 {
139 LeaveCriticalSection(&g_tt32_lock);
140 return TRUE;
141 }
142
143 // First, determine the name of the DLL we should try loading...
144
145 if ( !( pszDLLName = getenv( "HERCULES_IFC" ) ) )
146 pszDLLName = DEF_TT32_DLLNAME;
147
148 ASSERT( pszDLLName && *pszDLLName );
149
150 // Then check to see if the "name" contains path information or not...
151
152 if ( strchr( pszDLLName, '/' ) || strchr( pszDLLName, '\\' ) )
153 {
154 // It's already a path...
155 strlcpy( tt32_dllname_in_buff, pszDLLName, sizeof(tt32_dllname_in_buff) );
156 }
157 else
158 {
159 // It's not a path, so make it one...
160 strlcpy( tt32_dllname_in_buff, MODULESDIR, sizeof(tt32_dllname_in_buff) );
161 strlcat( tt32_dllname_in_buff, "/" , sizeof(tt32_dllname_in_buff) );
162 strlcat( tt32_dllname_in_buff, pszDLLName, sizeof(tt32_dllname_in_buff) );
163 }
164
165 // Now convert it to a full path...
166
167 // PROGRAMMING NOTE: It's important here to ensure that our end result is a path
168 // with BACKWARD slashes in it and NOT forward slashes! LoadLibrary is one of the
169 // few Win32 functions that cannot handle paths with forward slashes in it. For
170 // 'open', etc, yeah, forward slashes are fine, but for LoadLibrary they're not!
171
172 #ifdef _MSVC_
173 if ( !_fullpath( tt32_dllname_out_buff, tt32_dllname_in_buff, sizeof(tt32_dllname_out_buff) ) )
174 strlcpy( tt32_dllname_out_buff, tt32_dllname_in_buff, sizeof(tt32_dllname_out_buff) );
175 #else // (presumed cygwin)
176 cygwin_conv_to_full_win32_path( tt32_dllname_in_buff, tt32_dllname_out_buff );
177 #endif // _MSVC_
178
179 tt32_dllname_out_buff[ sizeof(tt32_dllname_out_buff) - 1 ] = 0;
180
181 // Finally, copy it to our global home for it...
182
183 strlcpy( g_tt32_dllname, tt32_dllname_out_buff, sizeof(g_tt32_dllname) );
184
185 ASSERT(g_tt32_dllname[0]);
186
187 g_tt32_hmoddll = LoadLibraryEx( g_tt32_dllname, NULL, LOAD_WITH_ALTERED_SEARCH_PATH );
188
189 if (!g_tt32_hmoddll)
190 {
191 // Try again WITHOUT the path this time...
192
193 strlcpy( g_tt32_dllname, pszDLLName, sizeof(g_tt32_dllname) );
194
195 g_tt32_hmoddll = LoadLibraryEx( g_tt32_dllname, NULL, LOAD_WITH_ALTERED_SEARCH_PATH );
196
197 if (!g_tt32_hmoddll)
198 {
199 DWORD dwLastError = GetLastError();
200 LeaveCriticalSection(&g_tt32_lock);
201 logmsg("** tt32_loaddll: LoadLibraryEx(\"%s\") failed; rc=%ld: %s\n",
202 g_tt32_dllname,dwLastError,strerror(dwLastError));
203 return FALSE;
204 }
205 }
206
207 // Resolve our required DLL entry-point variables...
208
209 if (!GetTT32ProcAddrs())
210 return FALSE;
211
212 logmsg("%s version %s initiated\n",
213 g_tt32_dllname,
214 g_tt32_pfn_version_string());
215
216 #if defined(DEBUG) || defined(_DEBUG)
217 enable_tt32_debug_tracing(1); // (enable debug tracing by default for DEBUG builds)
218 #endif
219
220 return TRUE;
221 }
222
223 ///////////////////////////////////////////////////////////////////////////////////////////
224
tt32_open(char * pszGatewayDevice,int iFlags)225 int tt32_open( char* pszGatewayDevice, int iFlags )
226 {
227 int rc, errnum;
228 if (!tt32_loaddll()) return -1;
229 if (! g_tt32_pfn_open_ex )
230 return g_tt32_pfn_open ( pszGatewayDevice, iFlags );
231 rc = g_tt32_pfn_open_ex ( pszGatewayDevice, iFlags, &errnum );
232 errno = errnum;
233 return rc;
234 }
235
236 ///////////////////////////////////////////////////////////////////////////////////////////
237
tt32_read(int fd,u_char * buffer,u_long size)238 int tt32_read( int fd, u_char* buffer, u_long size )
239 {
240 int rc, errnum;
241 if (!tt32_loaddll()) return -1;
242 if (! g_tt32_pfn_read_ex )
243 return g_tt32_pfn_read ( fd, buffer, size );
244 rc = g_tt32_pfn_read_ex ( fd, buffer, size, &errnum );
245 errno = errnum;
246 return rc;
247 }
248
249 ///////////////////////////////////////////////////////////////////////////////////////////
250
tt32_write(int fd,u_char * buffer,u_long size)251 int tt32_write( int fd, u_char* buffer, u_long size )
252 {
253 int rc, errnum;
254 if (!tt32_loaddll()) return -1;
255 if (! g_tt32_pfn_write_ex )
256 return g_tt32_pfn_write ( fd, buffer, size );
257 rc = g_tt32_pfn_write_ex ( fd, buffer, size, &errnum );
258 errno = errnum;
259 return rc;
260 }
261
262 ///////////////////////////////////////////////////////////////////////////////////////////
263
tt32_close(int fd)264 int tt32_close( int fd )
265 {
266 int rc, errnum;
267 if (!tt32_loaddll()) return -1;
268 #if defined(DEBUG) || defined(_DEBUG)
269 display_tt32_stats(fd);
270 #endif
271 if (! g_tt32_pfn_close_ex )
272 return g_tt32_pfn_close ( fd );
273 rc = g_tt32_pfn_close_ex ( fd, &errnum );
274 errno = errnum;
275 return rc;
276 }
277
278 ///////////////////////////////////////////////////////////////////////////////////////////
279
tt32_ioctl(int fd,int iRequest,char * argp)280 int tt32_ioctl( int fd, int iRequest, char* argp )
281 {
282 int rc, errnum;
283 if (!tt32_loaddll()) return -1;
284 if (! g_tt32_pfn_ioctl_ex )
285 return g_tt32_pfn_ioctl ( fd, iRequest, argp );
286 rc = g_tt32_pfn_ioctl_ex ( fd, iRequest, argp, &errnum );
287 errno = errnum;
288 return rc;
289 }
290
291 ///////////////////////////////////////////////////////////////////////////////////////////
292
tt32_get_default_iface()293 const char* tt32_get_default_iface()
294 {
295 int errnum;
296 const char* pszDefaultIFace = NULL;
297 if (tt32_loaddll())
298 {
299 if (! g_tt32_pfn_get_default_iface_ex )
300 pszDefaultIFace = g_tt32_pfn_get_default_iface ();
301 else { pszDefaultIFace = g_tt32_pfn_get_default_iface_ex ( &errnum );
302 errno = errnum;
303 }
304 }
305 return ( pszDefaultIFace ? pszDefaultIFace : TT32_DEFAULT_IFACE );
306 }
307
308 ///////////////////////////////////////////////////////////////////////////////////////////
309
display_tt32_stats(int fd)310 int display_tt32_stats( int fd )
311 {
312 int errnum;
313 TT32STATS stats;
314
315 if (!tt32_loaddll()) return -1;
316
317 memset(&stats,0,sizeof(stats));
318 stats.dwStructSize = sizeof(stats);
319
320 if (! g_tt32_pfn_get_stats_ex )
321 g_tt32_pfn_get_stats ( fd, &stats );
322 else { g_tt32_pfn_get_stats_ex ( fd, &stats, &errnum );
323 errno = errnum;
324 }
325
326 if (stats.dwStructSize >= sizeof(stats))
327 {
328 // New version 3.3 stats
329
330 logmsg
331 (
332 "\n%s Statistics:\n\n"
333
334 "Size of Kernel Hold Buffer: %5luK\n"
335 "Size of DLL I/O Buffer: %5luK\n"
336 "Maximum DLL I/O Bytes Received: %5luK\n\n"
337
338 "%12" I64_FMT "d Total Write Calls\n"
339 "%12" I64_FMT "d Total Write I/Os\n"
340 "%12" I64_FMT "d Packets To All Zeroes MAC Written\n"
341 "%12" I64_FMT "d Total Packets Written\n"
342 "%12" I64_FMT "d Total Bytes Written\n\n"
343
344 "%12" I64_FMT "d Total Read Calls\n"
345 "%12" I64_FMT "d Total Read I/Os\n"
346 "%12" I64_FMT "d Internally Handled ARP Packets\n"
347 "%12" I64_FMT "d Packets From Ourself\n"
348 "%12" I64_FMT "d Total Ignored Packets\n"
349 "%12" I64_FMT "d Packets To All Zeroes MAC Read\n"
350 "%12" I64_FMT "d Total Packets Read\n"
351 "%12" I64_FMT "d Total Bytes Read\n\n"
352
353 ,g_tt32_dllname
354
355 ,(stats.dwKernelBuffSize + 1023) / 1024
356 ,(stats.dwReadBuffSize + 1023) / 1024
357 ,(stats.dwMaxBytesReceived + 1023) / 1024
358
359 ,stats.n64WriteCalls
360 ,stats.n64WriteIOs
361 ,stats.n64ZeroMACPacketsWritten
362 ,stats.n64PacketsWritten
363 ,stats.n64BytesWritten
364
365 ,stats.n64ReadCalls
366 ,stats.n64ReadIOs
367 ,stats.n64InternalPackets
368 ,stats.n64OwnPacketsIgnored
369 ,stats.n64IgnoredPackets
370 ,stats.n64ZeroMACPacketsRead
371 ,stats.n64PacketsRead
372 ,stats.n64BytesRead
373 );
374 }
375 else
376 {
377 // Old pre version 3.3 stats
378
379 logmsg
380 (
381 "\n%s Statistics:\n\n"
382
383 "Size of Kernel Hold Buffer: %5luK\n"
384 "Size of DLL I/O Buffer: %5luK\n"
385 "Maximum DLL I/O Bytes Received: %5luK\n\n"
386
387 "%12" I64_FMT "d Write Calls\n"
388 "%12" I64_FMT "d Write I/Os\n"
389 "%12" I64_FMT "d Read Calls\n"
390 "%12" I64_FMT "d Read I/Os\n"
391 "%12" I64_FMT "d Packets Read\n"
392 "%12" I64_FMT "d Packets Written\n"
393 "%12" I64_FMT "d Bytes Read\n"
394 "%12" I64_FMT "d Bytes Written\n"
395 "%12" I64_FMT "d Internal Packets\n"
396 "%12" I64_FMT "d Ignored Packets\n\n"
397 ,
398 g_tt32_dllname
399 ,(stats.dwKernelBuffSize + 1023) / 1024
400 ,(stats.dwReadBuffSize + 1023) / 1024
401 ,(stats.dwMaxBytesReceived + 1023) / 1024
402 ,stats.n64WriteCalls
403 ,stats.n64WriteIOs
404 ,stats.n64ReadCalls
405 ,stats.n64ReadIOs
406 ,stats.n64PacketsRead
407 ,stats.n64PacketsWritten
408 ,stats.n64BytesRead
409 ,stats.n64BytesWritten
410 ,stats.n64InternalPackets
411 ,stats.n64IgnoredPackets
412 );
413 }
414
415 return 0;
416 }
417
418 ///////////////////////////////////////////////////////////////////////////////////////////
419 // BOOLEAN FUNCTION
420
tt32_build_herc_iface_mac(BYTE * out_mac,const BYTE * in_ip)421 int tt32_build_herc_iface_mac ( BYTE* out_mac, const BYTE* in_ip )
422 {
423 // We prefer to let TunTap32 do it for us (since IT'S the one
424 // that decides what it should really be) but if they're using
425 // an older version of TunTap32 that doesn't have the function
426 // then we'll do it ourselves just like before...
427
428 if (!g_tt32_pfn_build_herc_iface_mac)
429 return 0; // (FALSE: must do it yourself)
430
431 g_tt32_pfn_build_herc_iface_mac( out_mac, in_ip );
432 return 1; // (TRUE: ok we did it for you)
433 }
434
435 ///////////////////////////////////////////////////////////////////////////////////////////
436
437 #endif // !defined(OPTION_W32_CTCI)
438
439 ///////////////////////////////////////////////////////////////////////////////////////////
440