1 /* CTC_CTCI.C (c) Copyright Roger Bowler, 2000-2012 */
2 /* (c) Copyright James A. Pierson, 2002-2009 */
3 /* (c) Copyright "Fish" (David B. Trout), 2002-2009 */
4 /* (c) Copyright Fritz Elfert, 2001-2009 */
5 /* Hercules IP Channel-to-Channel Support (CTCI) */
6
7 #include "hstdinc.h"
8
9 /* jbs 10/27/2007 added _SOLARIS_ silly typo fixed 01/18/08 when looked at this again */
10 #if !defined(__SOLARIS__)
11
12 #include "hercules.h"
13 #include "ctcadpt.h"
14 #include "tuntap.h"
15 #include "hercifc.h"
16 #include "opcode.h"
17 /* getopt dynamic linking kludge */
18 #include "herc_getopt.h"
19 #if defined(OPTION_W32_CTCI)
20 #include "tt32api.h"
21 #endif
22
23 /*-------------------------------------------------------------------*/
24 /* Ivan Warren 20040227 */
25 /* This table is used by channel.c to determine if a CCW code is an */
26 /* immediate command or not */
27 /* The tape is addressed in the DEVHND structure as 'DEVIMM immed' */
28 /* 0 : Command is NOT an immediate command */
29 /* 1 : Command is an immediate command */
30 /* Note : An immediate command is defined as a command which returns */
31 /* CE (channel end) during initialisation (that is, no data is */
32 /* actually transfered. In this case, IL is not indicated for a CCW */
33 /* Format 0 or for a CCW Format 1 when IL Suppression Mode is in */
34 /* effect */
35 /*-------------------------------------------------------------------*/
36
37 static BYTE CTCI_Immed_Commands[256]=
38 { 0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,
39 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
40 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
41 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
42 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
43 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
44 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
45 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
46 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
47 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
48 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
49 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
50 0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,
51 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
52 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
53 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
54
55 // ====================================================================
56 // Declarations
57 // ====================================================================
58
59 static void* CTCI_ReadThread( PCTCBLK pCTCBLK );
60
61 static int CTCI_EnqueueIPFrame( DEVBLK* pDEVBLK,
62 BYTE* pData, size_t iSize );
63
64 static int ParseArgs( DEVBLK* pDEVBLK, PCTCBLK pCTCBLK,
65 int argc, char** argv );
66
67 // --------------------------------------------------------------------
68 // Device Handler Information Block
69 // --------------------------------------------------------------------
70
71 DEVHND ctci_device_hndinfo =
72 {
73 &CTCI_Init, /* Device Initialisation */
74 &CTCI_ExecuteCCW, /* Device CCW execute */
75 &CTCI_Close, /* Device Close */
76 &CTCI_Query, /* Device Query */
77 NULL, /* Device Start channel pgm */
78 NULL, /* Device End channel pgm */
79 NULL, /* Device Resume channel pgm */
80 NULL, /* Device Suspend channel pgm */
81 NULL, /* Device Read */
82 NULL, /* Device Write */
83 NULL, /* Device Query used */
84 NULL, /* Device Reserve */
85 NULL, /* Device Release */
86 NULL, /* Device Attention */
87 CTCI_Immed_Commands, /* Immediate CCW Codes */
88 NULL, /* Signal Adapter Input */
89 NULL, /* Signal Adapter Output */
90 NULL, /* Hercules suspend */
91 NULL /* Hercules resume */
92 };
93
94 // ====================================================================
95 //
96 // ====================================================================
97
98 //
99 // CTCI_Init
100 //
101
102 #define CTC_DEVICES_IN_GROUP 2 // a read and write device
103
CTCI_Init(DEVBLK * pDEVBLK,int argc,char * argv[])104 int CTCI_Init( DEVBLK* pDEVBLK, int argc, char *argv[] )
105 {
106 PCTCBLK pWrkCTCBLK = NULL; // Working CTCBLK
107 PCTCBLK pDevCTCBLK = NULL; // Device CTCBLK
108 int rc = 0; // Return code
109 int nIFType; // Interface type
110 int nIFFlags; // Interface flags
111 char thread_name[32]; // CTCI_ReadThread
112
113 nIFType = // Interface type
114 0
115 | IFF_TUN // ("TUN", not "tap")
116 | IFF_NO_PI // (no packet info)
117 ;
118
119 nIFFlags = // Interface flags
120 0
121 | IFF_UP // (interface is being enabled)
122 | IFF_BROADCAST // (interface broadcast addr is valid)
123 ;
124
125 #if defined( TUNTAP_IFF_RUNNING_NEEDED )
126
127 nIFFlags |= // ADDITIONAL Interface flags
128 0
129 | IFF_RUNNING // (interface is ALSO operational)
130 ;
131
132 #endif /* defined( TUNTAP_IFF_RUNNING_NEEDED ) */
133
134 pDEVBLK->devtype = 0x3088;
135
136 // CTC is a group device
137 if(!group_device(pDEVBLK, CTC_DEVICES_IN_GROUP))
138 return 0;
139
140 // Housekeeping
141 pWrkCTCBLK = malloc( sizeof( CTCBLK ) );
142
143 if( !pWrkCTCBLK )
144 {
145 logmsg( _("HHCCT037E %4.4X: Unable to allocate CTCBLK\n"),
146 pDEVBLK->devnum );
147 return -1;
148 }
149
150 memset( pWrkCTCBLK, 0, sizeof( CTCBLK ) );
151
152 // Parse configuration file statement
153 if( ParseArgs( pDEVBLK, pWrkCTCBLK, argc, (char**)argv ) != 0 )
154 {
155 free( pWrkCTCBLK );
156 pWrkCTCBLK = NULL;
157 return -1;
158 }
159
160 // Allocate the device CTCBLK and copy parsed information.
161
162 pDevCTCBLK = malloc( sizeof( CTCBLK ) );
163
164 if( !pDevCTCBLK )
165 {
166 logmsg( _("HHCCT038E %4.4X: Unable to allocate CTCBLK\n"),
167 pDEVBLK->devnum );
168 free( pWrkCTCBLK );
169 pWrkCTCBLK = NULL;
170 return -1;
171 }
172
173 memcpy( pDevCTCBLK, pWrkCTCBLK, sizeof( CTCBLK ) );
174
175 // New format has only one device statement for both addresses
176 // We need to dynamically allocate the read device block
177
178 pDevCTCBLK->pDEVBLK[0] = pDEVBLK->group->memdev[0];
179 pDevCTCBLK->pDEVBLK[1] = pDEVBLK->group->memdev[1];
180
181 pDevCTCBLK->pDEVBLK[0]->dev_data = pDevCTCBLK;
182 pDevCTCBLK->pDEVBLK[1]->dev_data = pDevCTCBLK;
183
184 SetSIDInfo( pDevCTCBLK->pDEVBLK[0], 0x3088, 0x08, 0x3088, 0x01 );
185 SetSIDInfo( pDevCTCBLK->pDEVBLK[1], 0x3088, 0x08, 0x3088, 0x01 );
186
187 pDevCTCBLK->pDEVBLK[0]->ctctype = CTC_CTCI;
188 pDevCTCBLK->pDEVBLK[0]->ctcxmode = 1;
189
190 pDevCTCBLK->pDEVBLK[1]->ctctype = CTC_CTCI;
191 pDevCTCBLK->pDEVBLK[1]->ctcxmode = 1;
192
193 pDevCTCBLK->sMTU = atoi( pDevCTCBLK->szMTU );
194 pDevCTCBLK->iMaxFrameBufferSize = sizeof(pDevCTCBLK->bFrameBuffer);
195
196 initialize_lock( &pDevCTCBLK->Lock );
197 initialize_lock( &pDevCTCBLK->EventLock );
198 initialize_condition( &pDevCTCBLK->Event );
199
200 // Give both Herc devices a reasonable name...
201
202 strlcpy( pDevCTCBLK->pDEVBLK[0]->filename,
203 pDevCTCBLK->szTUNCharName,
204 sizeof( pDevCTCBLK->pDEVBLK[0]->filename ) );
205
206 strlcpy( pDevCTCBLK->pDEVBLK[1]->filename,
207 pDevCTCBLK->szTUNCharName,
208 sizeof( pDevCTCBLK->pDEVBLK[1]->filename ) );
209
210 rc = TUNTAP_CreateInterface( pDevCTCBLK->szTUNCharName,
211 IFF_TUN | IFF_NO_PI,
212 &pDevCTCBLK->fd,
213 pDevCTCBLK->szTUNDevName );
214
215 if( rc < 0 )
216 {
217 free( pWrkCTCBLK );
218 pWrkCTCBLK = NULL;
219 return -1;
220 }
221 else
222 {
223 logmsg(_("HHCCT073I %4.4X: TUN device %s opened\n"),
224 pDevCTCBLK->pDEVBLK[0]->devnum,
225 pDevCTCBLK->szTUNDevName);
226 }
227
228 #if defined(OPTION_W32_CTCI)
229
230 // Set the specified driver/dll i/o buffer sizes..
231 {
232 struct tt32ctl tt32ctl;
233
234 memset( &tt32ctl, 0, sizeof(tt32ctl) );
235 strlcpy( tt32ctl.tt32ctl_name, pDevCTCBLK->szTUNDevName, sizeof(tt32ctl.tt32ctl_name) );
236
237 tt32ctl.tt32ctl_devbuffsize = pDevCTCBLK->iKernBuff;
238 if( TUNTAP_IOCtl( pDevCTCBLK->fd, TT32SDEVBUFF, (char*)&tt32ctl ) != 0 )
239 {
240 logmsg( _("HHCCT074W TT32SDEVBUFF failed for device %s: %s.\n"),
241 pDevCTCBLK->szTUNDevName, strerror( errno ) );
242 }
243
244 tt32ctl.tt32ctl_iobuffsize = pDevCTCBLK->iIOBuff;
245 if( TUNTAP_IOCtl( pDevCTCBLK->fd, TT32SIOBUFF, (char*)&tt32ctl ) != 0 )
246 {
247 logmsg( _("HHCCT075W TT32SIOBUFF failed for device %s: %s.\n"),
248 pDevCTCBLK->szTUNDevName, strerror( errno ) );
249 }
250 }
251 #endif
252
253 #ifdef OPTION_TUNTAP_CLRIPADDR
254 VERIFY( TUNTAP_ClrIPAddr ( pDevCTCBLK->szTUNDevName ) == 0 );
255 #endif
256
257 #ifdef OPTION_TUNTAP_SETMACADDR
258
259 if( !pDevCTCBLK->szMACAddress[0] ) // (if MAC address unspecified)
260 {
261 in_addr_t wrk_guest_ip_addr;
262 MAC wrk_guest_mac_addr;
263
264 if ((in_addr_t)-1 != (wrk_guest_ip_addr = inet_addr( pDevCTCBLK->szGuestIPAddr )))
265 {
266 build_herc_iface_mac ( wrk_guest_mac_addr, (const BYTE*) &wrk_guest_ip_addr );
267
268 snprintf
269 (
270 pDevCTCBLK->szMACAddress, sizeof( pDevCTCBLK->szMACAddress ),
271
272 "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X"
273
274 ,wrk_guest_mac_addr[0]
275 ,wrk_guest_mac_addr[1]
276 ,wrk_guest_mac_addr[2]
277 ,wrk_guest_mac_addr[3]
278 ,wrk_guest_mac_addr[4]
279 ,wrk_guest_mac_addr[5]
280 );
281 }
282 }
283
284 TRACE
285 (
286 "** CTCI_Init: %4.4X (%s): IP \"%s\" --> default MAC \"%s\"\n"
287
288 ,pDevCTCBLK->pDEVBLK[0]->devnum
289 ,pDevCTCBLK->szTUNDevName
290 ,pDevCTCBLK->szGuestIPAddr
291 ,pDevCTCBLK->szMACAddress
292 );
293
294 VERIFY( TUNTAP_SetMACAddr ( pDevCTCBLK->szTUNDevName, pDevCTCBLK->szMACAddress ) == 0 );
295 #endif
296
297 VERIFY( TUNTAP_SetIPAddr ( pDevCTCBLK->szTUNDevName, pDevCTCBLK->szDriveIPAddr ) == 0 );
298
299 VERIFY( TUNTAP_SetDestAddr( pDevCTCBLK->szTUNDevName, pDevCTCBLK->szGuestIPAddr ) == 0 );
300
301 #ifdef OPTION_TUNTAP_SETNETMASK
302 VERIFY( TUNTAP_SetNetMask ( pDevCTCBLK->szTUNDevName, pDevCTCBLK->szNetMask ) == 0 );
303 #endif
304
305 VERIFY( TUNTAP_SetMTU ( pDevCTCBLK->szTUNDevName, pDevCTCBLK->szMTU ) == 0 );
306
307 VERIFY( TUNTAP_SetFlags ( pDevCTCBLK->szTUNDevName, nIFFlags ) == 0 );
308
309 // Copy the fd to make panel.c happy
310 pDevCTCBLK->pDEVBLK[0]->fd =
311 pDevCTCBLK->pDEVBLK[1]->fd = pDevCTCBLK->fd;
312
313 snprintf(thread_name,sizeof(thread_name),"CTCI %4.4X ReadThread",pDEVBLK->devnum);
314 thread_name[sizeof(thread_name)-1]=0;
315 create_thread( &pDevCTCBLK->tid, JOINABLE, CTCI_ReadThread, pDevCTCBLK, thread_name );
316
317 pDevCTCBLK->pDEVBLK[0]->tid = pDevCTCBLK->tid;
318 pDevCTCBLK->pDEVBLK[1]->tid = pDevCTCBLK->tid;
319
320 free( pWrkCTCBLK );
321 pWrkCTCBLK = NULL;
322
323 return 0;
324 }
325
326
327 //
328 // CTCI_ExecuteCCW
329 //
CTCI_ExecuteCCW(DEVBLK * pDEVBLK,BYTE bCode,BYTE bFlags,BYTE bChained,U16 sCount,BYTE bPrevCode,int iCCWSeq,BYTE * pIOBuf,BYTE * pMore,BYTE * pUnitStat,U16 * pResidual)330 void CTCI_ExecuteCCW( DEVBLK* pDEVBLK, BYTE bCode,
331 BYTE bFlags, BYTE bChained,
332 U16 sCount, BYTE bPrevCode,
333 int iCCWSeq, BYTE* pIOBuf,
334 BYTE* pMore, BYTE* pUnitStat,
335 U16* pResidual )
336 {
337 int iNum; // Number of bytes to move
338 BYTE bOpCode; // CCW opcode with modifier
339 // bits masked off
340
341 UNREFERENCED( bFlags );
342 UNREFERENCED( bChained );
343 UNREFERENCED( bPrevCode );
344 UNREFERENCED( iCCWSeq );
345
346 // Intervention required if the device file is not open
347 if( pDEVBLK->fd < 0 &&
348 !IS_CCW_SENSE( bCode ) &&
349 !IS_CCW_CONTROL( bCode ) )
350 {
351 pDEVBLK->sense[0] = SENSE_IR;
352 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
353 return;
354 }
355
356 // Mask off the modifier bits in the CCW bOpCode
357 if( ( bCode & 0x07 ) == 0x07 )
358 bOpCode = 0x07;
359 else if( ( bCode & 0x03 ) == 0x02 )
360 bOpCode = 0x02;
361 else if( ( bCode & 0x0F ) == 0x0C )
362 bOpCode = 0x0C;
363 else if( ( bCode & 0x03 ) == 0x01 )
364 bOpCode = pDEVBLK->ctcxmode ? ( bCode & 0x83 ) : 0x01;
365 else if( ( bCode & 0x1F ) == 0x14 )
366 bOpCode = 0x14;
367 else if( ( bCode & 0x47 ) == 0x03 )
368 bOpCode = 0x03;
369 else if( ( bCode & 0xC7 ) == 0x43 )
370 bOpCode = 0x43;
371 else
372 bOpCode = bCode;
373
374 // Process depending on CCW bOpCode
375 switch (bOpCode)
376 {
377 case 0x01: // 0MMMMM01 WRITE
378 //------------------------------------------------------------
379 // WRITE
380 //------------------------------------------------------------
381
382 // Return normal status if CCW count is zero
383 if( sCount == 0 )
384 {
385 *pUnitStat = CSW_CE | CSW_DE;
386 break;
387 }
388
389 CTCI_Write( pDEVBLK, sCount, pIOBuf, pUnitStat, pResidual );
390 break;
391
392 case 0x81: // 1MMMMM01 WEOF
393 //------------------------------------------------------------
394 // WRITE EOF
395 //------------------------------------------------------------
396
397 // Return normal status
398 *pUnitStat = CSW_CE | CSW_DE;
399 break;
400
401 case 0x02: // MMMMMM10 READ
402 case 0x0C: // MMMM1100 RDBACK
403 // -----------------------------------------------------------
404 // READ & READ BACKWARDS
405 // -----------------------------------------------------------
406
407 // Read data and set unit status and residual byte count
408 CTCI_Read( pDEVBLK, sCount, pIOBuf, pUnitStat, pResidual, pMore );
409 break;
410
411 case 0x07: // MMMMM111 CTL
412 // -----------------------------------------------------------
413 // CONTROL
414 // -----------------------------------------------------------
415
416 *pUnitStat = CSW_CE | CSW_DE;
417 break;
418
419 case 0x03: // M0MMM011 NOP
420 // -----------------------------------------------------------
421 // CONTROL NO-OPERATON
422 // -----------------------------------------------------------
423
424 *pUnitStat = CSW_CE | CSW_DE;
425 break;
426
427 case 0x43: // 00XXX011 SBM
428 // -----------------------------------------------------------
429 // SET BASIC MODE
430 // -----------------------------------------------------------
431
432 // Command reject if in basic mode
433 if( pDEVBLK->ctcxmode == 0 )
434 {
435 pDEVBLK->sense[0] = SENSE_CR;
436 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
437
438 break;
439 }
440
441 // Reset extended mode and return normal status
442 pDEVBLK->ctcxmode = 0;
443
444 *pResidual = 0;
445 *pUnitStat = CSW_CE | CSW_DE;
446
447 break;
448
449 case 0xC3: // 11000011 SEM
450 // -----------------------------------------------------------
451 // SET EXTENDED MODE
452 // -----------------------------------------------------------
453
454 pDEVBLK->ctcxmode = 1;
455
456 *pResidual = 0;
457 *pUnitStat = CSW_CE | CSW_DE;
458
459 break;
460
461 case 0xE3: // 11100011
462 // -----------------------------------------------------------
463 // PREPARE (PREP)
464 // -----------------------------------------------------------
465
466 *pUnitStat = CSW_CE | CSW_DE;
467
468 break;
469
470 case 0x14: // XXX10100 SCB
471 // -----------------------------------------------------------
472 // SENSE COMMAND BYTE
473 // -----------------------------------------------------------
474
475 *pUnitStat = CSW_CE | CSW_DE;
476 break;
477
478 case 0x04: // 00000100 SENSE
479 // -----------------------------------------------------------
480 // SENSE
481 // -----------------------------------------------------------
482
483 // Command reject if in basic mode
484 if( pDEVBLK->ctcxmode == 0 )
485 {
486 pDEVBLK->sense[0] = SENSE_CR;
487 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
488 break;
489 }
490
491 // Calculate residual byte count
492 iNum = ( sCount < pDEVBLK->numsense ) ?
493 sCount : pDEVBLK->numsense;
494
495 *pResidual = sCount - iNum;
496
497 if( sCount < pDEVBLK->numsense )
498 *pMore = 1;
499
500 // Copy device sense bytes to channel I/O buffer
501 memcpy( pIOBuf, pDEVBLK->sense, iNum );
502
503 // Clear the device sense bytes
504 memset( pDEVBLK->sense, 0, sizeof( pDEVBLK->sense ) );
505
506 // Return unit status
507 *pUnitStat = CSW_CE | CSW_DE;
508
509 break;
510
511 case 0xE4: // 11100100 SID
512 // -----------------------------------------------------------
513 // SENSE ID
514 // -----------------------------------------------------------
515
516 // Calculate residual byte count
517 iNum = ( sCount < pDEVBLK->numdevid ) ?
518 sCount : pDEVBLK->numdevid;
519
520 *pResidual = sCount - iNum;
521
522 if( sCount < pDEVBLK->numdevid )
523 *pMore = 1;
524
525 // Copy device identifier bytes to channel I/O buffer
526 memcpy( pIOBuf, pDEVBLK->devid, iNum );
527
528 // Return unit status
529 *pUnitStat = CSW_CE | CSW_DE;
530
531 break;
532
533 default:
534 // ------------------------------------------------------------
535 // INVALID OPERATION
536 // ------------------------------------------------------------
537
538 // Set command reject sense byte, and unit check status
539 pDEVBLK->sense[0] = SENSE_CR;
540 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
541 }
542 }
543
544 // -------------------------------------------------------------------
545 // CTCI_Close
546 // -------------------------------------------------------------------
547
CTCI_Close(DEVBLK * pDEVBLK)548 int CTCI_Close( DEVBLK* pDEVBLK )
549 {
550 /* DEVBLK* pDEVBLK2; */
551 PCTCBLK pCTCBLK = (PCTCBLK)pDEVBLK->dev_data;
552
553 // Close the device file (if not already closed)
554 if( pCTCBLK->fd >= 0 )
555 {
556 // PROGRAMMING NOTE: there's currently no way to interrupt
557 // the "CTCI_ReadThread"s TUNTAP_Read of the adapter. Thus
558 // we must simply wait for CTCI_ReadThread to eventually
559 // notice that we're doing a close (via our setting of the
560 // fCloseInProgress flag). Its TUNTAP_Read will eventually
561 // timeout after a few seconds (currently 5, which is dif-
562 // ferent than the CTC_READ_TIMEOUT_SECS timeout value the
563 // CTCI_Read function uses) and will then do the close of
564 // the adapter for us (TUNTAP_Close) so we don't have to.
565 // All we need to do is ask it to exit (via our setting of
566 // the fCloseInProgress flag) and then wait for it to exit
567 // (which, as stated, could take up to a max of 5 seconds).
568
569 // All of this is simply because it's poor form to close a
570 // device from one thread while another thread is reading
571 // from it. Attempting to do so could trip a race condition
572 // wherein the internal i/o buffers used to process the
573 // read request could have been freed (by the close call)
574 // by the time the read request eventually gets serviced.
575
576 TID tid = pCTCBLK->tid;
577 pCTCBLK->fCloseInProgress = 1; // (ask read thread to exit)
578 signal_thread( tid, SIGUSR2 ); // (for non-Win32 platforms)
579 //FIXME signal_thread not working for non-MSVC platforms
580 #if defined(_MSVC_)
581 join_thread( tid, NULL ); // (wait for thread to end)
582 #endif
583 detach_thread( tid ); // (wait for thread to end)
584 }
585
586 pDEVBLK->fd = -1; // indicate we're now closed
587
588 return 0;
589 }
590
591
592 // -------------------------------------------------------------------
593 // CTCI_Query
594 // -------------------------------------------------------------------
595
CTCI_Query(DEVBLK * pDEVBLK,char ** ppszClass,int iBufLen,char * pBuffer)596 void CTCI_Query( DEVBLK* pDEVBLK, char** ppszClass,
597 int iBufLen, char* pBuffer )
598 {
599 CTCBLK* pCTCBLK;
600
601 BEGIN_DEVICE_CLASS_QUERY( "CTCA", pDEVBLK, ppszClass, iBufLen, pBuffer );
602
603 pCTCBLK = (CTCBLK*) pDEVBLK->dev_data;
604
605 if(!pCTCBLK)
606 {
607 strlcpy(pBuffer,"*Uninitialized",iBufLen);
608 return;
609 }
610
611 snprintf( pBuffer, iBufLen, "CTCI %s/%s (%s)%s",
612 pCTCBLK->szGuestIPAddr,
613 pCTCBLK->szDriveIPAddr,
614 pCTCBLK->szTUNDevName,
615 pCTCBLK->fDebug ? " -d" : "" );
616 }
617
618 // -------------------------------------------------------------------
619 // CTCI_Read
620 // -------------------------------------------------------------------
621 //
622 // Once an IP frame is received by the Read Thread, it is enqueued
623 // on the device frame buffer for presentation to the host program.
624 // The residual byte count is set to indicate the amount of the buffer
625 // which was not filled.
626 //
627 // For details regarding the actual buffer layout, please refer to
628 // the comments preceding the CTCI_ReadThread function.
629
630 // Input:
631 // pDEVBLK A pointer to the CTC adapter device block
632 // sCount The I/O buffer length from the read CCW
633 // pIOBuf The I/O buffer from the read CCW
634 //
635 // Output:
636 // pUnitStat The CSW status (CE+DE or CE+DE+UC or CE+DE+UC+SM)
637 // pResidual The CSW residual byte count
638 // pMore Set to 1 if packet data exceeds CCW count
639 //
640
CTCI_Read(DEVBLK * pDEVBLK,U16 sCount,BYTE * pIOBuf,BYTE * pUnitStat,U16 * pResidual,BYTE * pMore)641 void CTCI_Read( DEVBLK* pDEVBLK, U16 sCount,
642 BYTE* pIOBuf, BYTE* pUnitStat,
643 U16* pResidual, BYTE* pMore )
644 {
645 PCTCBLK pCTCBLK = (PCTCBLK)pDEVBLK->dev_data;
646 PCTCIHDR pFrame = NULL;
647 size_t iLength = 0;
648 int rc = 0;
649
650 for ( ; ; )
651 {
652 obtain_lock( &pCTCBLK->Lock );
653
654 if( !pCTCBLK->fDataPending )
655 {
656 struct timespec waittime;
657 struct timeval now;
658
659 release_lock( &pCTCBLK->Lock );
660
661 gettimeofday( &now, NULL );
662
663 waittime.tv_sec = now.tv_sec + CTC_READ_TIMEOUT_SECS;
664 waittime.tv_nsec = now.tv_usec * 1000;
665
666 obtain_lock( &pCTCBLK->EventLock );
667 rc = timed_wait_condition( &pCTCBLK->Event,
668 &pCTCBLK->EventLock,
669 &waittime );
670 release_lock( &pCTCBLK->EventLock );
671
672 if( rc == ETIMEDOUT || rc == EINTR )
673 {
674 // check for halt condition
675 if( pDEVBLK->scsw.flag2 & SCSW2_FC_HALT ||
676 pDEVBLK->scsw.flag2 & SCSW2_FC_CLEAR )
677 {
678 if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep )
679 logmsg( _("HHCCT040I %4.4X: Halt or Clear Recognized\n"),
680 pDEVBLK->devnum );
681
682 *pUnitStat = CSW_CE | CSW_DE;
683 *pResidual = sCount;
684 return;
685 }
686
687 continue;
688 }
689
690 obtain_lock( &pCTCBLK->Lock );
691 }
692
693 // Sanity check
694 if( pCTCBLK->iFrameOffset == 0 )
695 {
696 release_lock( &pCTCBLK->Lock );
697 continue;
698 }
699
700 // Fix-up frame pointer and terminate block
701 pFrame = (PCTCIHDR)( pCTCBLK->bFrameBuffer +
702 sizeof( CTCIHDR ) +
703 pCTCBLK->iFrameOffset );
704
705 STORE_HW( pFrame->hwOffset, 0x0000 );
706
707 // (fix for day-1 bug offered by Vince Weaver [vince@deater.net])
708 // iLength = pCTCBLK->iFrameOffset + sizeof( CTCIHDR ) + 2;
709 iLength = pCTCBLK->iFrameOffset + sizeof( CTCIHDR );
710
711 if( sCount < iLength )
712 {
713 *pMore = 1;
714 *pResidual = 0;
715
716 iLength = sCount;
717 }
718 else
719 {
720 *pMore = 0;
721 *pResidual -= iLength;
722 }
723
724 *pUnitStat = CSW_CE | CSW_DE;
725
726 memcpy( pIOBuf, pCTCBLK->bFrameBuffer, iLength );
727
728 if( pCTCBLK->fDebug )
729 {
730 logmsg( _("HHCCT041I %4.4X: CTC Received Frame (%d bytes):\n"),
731 pDEVBLK->devnum, iLength );
732 packet_trace( pCTCBLK->bFrameBuffer, iLength );
733 }
734
735 // Reset frame buffer
736 pCTCBLK->iFrameOffset = 0;
737 pCTCBLK->fDataPending = 0;
738
739 release_lock( &pCTCBLK->Lock );
740
741 return;
742 }
743 }
744
745 // -------------------------------------------------------------------
746 // CTCI_Write
747 // -------------------------------------------------------------------
748 //
749 // For details regarding the actual buffer layout, please refer to
750 // the comments preceding the CTCI_ReadThread function.
751 //
752
CTCI_Write(DEVBLK * pDEVBLK,U16 sCount,BYTE * pIOBuf,BYTE * pUnitStat,U16 * pResidual)753 void CTCI_Write( DEVBLK* pDEVBLK, U16 sCount,
754 BYTE* pIOBuf, BYTE* pUnitStat,
755 U16* pResidual )
756 {
757 PCTCBLK pCTCBLK = (PCTCBLK)pDEVBLK->dev_data;
758 PCTCIHDR pFrame; // -> Frame header
759 PCTCISEG pSegment; // -> Segment in buffer
760 U16 sOffset; // Offset of next frame
761 U16 sSegLen; // Current segment length
762 U16 sDataLen; // Length of IP Frame data
763 int iPos; // Offset into buffer
764 U16 i; // Array subscript
765 int rc; // Return code
766 BYTE szStackID[33]; // VSE IP stack identity
767 U32 iStackCmd; // VSE IP stack command
768
769 // Check that CCW count is sufficient to contain block header
770 if( sCount < sizeof( CTCIHDR ) )
771 {
772 logmsg( _("HHCCT042E %4.4X: Write CCW count %u is invalid\n"),
773 pDEVBLK->devnum, sCount );
774
775 pDEVBLK->sense[0] = SENSE_DC;
776 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
777
778 return;
779 }
780
781 // Fix-up frame pointer
782 pFrame = (PCTCIHDR)pIOBuf;
783
784 // Extract the frame length from the header
785 FETCH_HW( sOffset, pFrame->hwOffset );
786
787 // Check for special VSE TCP/IP stack command packet
788 if( sOffset == 0 && sCount == 40 )
789 {
790 // Extract the 32-byte stack identity string
791 for( i = 0;
792 i < sizeof( szStackID ) - 1 && i < sCount - 4;
793 i++)
794 szStackID[i] = guest_to_host( pIOBuf[i+4] );
795 szStackID[i] = '\0';
796
797 // Extract the stack command word
798 FETCH_FW( iStackCmd, *((FWORD*)&pIOBuf[36]) );
799
800 // Display stack command and discard the packet
801 logmsg( _("HHCCT043I %4.4X: Interface command: %s %8.8X\n"),
802 pDEVBLK->devnum, szStackID, iStackCmd );
803
804 *pUnitStat = CSW_CE | CSW_DE;
805 *pResidual = 0;
806
807 return;
808 }
809
810 // Check for special L/390 initialization packet
811 if( sOffset == 0 )
812 {
813 // Return normal status and discard the packet
814 *pUnitStat = CSW_CE | CSW_DE;
815 *pResidual = 0;
816
817 return;
818 }
819
820 #if 0
821 // Notes: It appears that TurboLinux has gotten sloppy in their
822 // ways. They are now giving us buffer sizes that are
823 // greater than the CCW count, but the segment size
824 // is within the count.
825 // Check that the frame offset is valid
826 if( sOffset < sizeof( CTCIHDR ) || sOffset > sCount )
827 {
828 logmsg( _("CTC101W %4.4X: Write buffer contains invalid "
829 "frame offset %u\n"),
830 pDEVBLK->devnum, sOffset );
831
832 pDEVBLK->sense[0] = SENSE_CR;
833 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
834
835 return;
836 }
837 #endif
838
839 // Adjust the residual byte count
840 *pResidual -= sizeof( CTCIHDR );
841
842 // Process each segment in the buffer
843 for( iPos = sizeof( CTCIHDR );
844 iPos < sOffset;
845 iPos += sSegLen )
846 {
847 // Check that the segment is fully contained within the block
848 if( iPos + sizeof( CTCISEG ) > sOffset )
849 {
850 logmsg( _("HHCCT044E %4.4X: Write buffer contains incomplete "
851 "segment header at offset %4.4X\n"),
852 pDEVBLK->devnum, iPos );
853
854 pDEVBLK->sense[0] = SENSE_DC;
855 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
856 return;
857 }
858
859 // Fix-up segment header in the I/O buffer
860 pSegment = (PCTCISEG)(pIOBuf + iPos);
861
862 // Extract the segment length from the segment header
863 FETCH_HW( sSegLen, pSegment->hwLength );
864
865 // Check that the segment length is valid
866 if( ( sSegLen < sizeof( CTCISEG ) ) ||
867 ( iPos + sSegLen > sOffset ) ||
868 ( iPos + sSegLen > sCount ) )
869 {
870 logmsg( _("HHCCT045E %4.4X: Write buffer contains invalid "
871 "segment length %u at offset %4.4X\n"),
872 pDEVBLK->devnum, sSegLen, iPos );
873
874 pDEVBLK->sense[0] = SENSE_DC;
875 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
876 return;
877 }
878
879 // Calculate length of IP frame data
880 sDataLen = sSegLen - sizeof( CTCISEG );
881
882 // Trace the IP packet before sending to TUN device
883 if( pCTCBLK->fDebug )
884 {
885 logmsg( _("HHCCT046I %4.4X: Sending packet to %s:\n"),
886 pDEVBLK->devnum, pCTCBLK->szTUNDevName );
887 packet_trace( pSegment->bData, sDataLen );
888 }
889
890 // Write the IP packet to the TUN/TAP interface
891 rc = TUNTAP_Write( pCTCBLK->fd, pSegment->bData, sDataLen );
892
893 if( rc < 0 )
894 {
895 logmsg( _("HHCCT047E %4.4X: Error writing to %s: rc=%d errno=%d %s\n"),
896 pDEVBLK->devnum, pCTCBLK->szTUNDevName,
897 rc, errno, strerror(errno));
898 }
899
900 /* Kludge for Ubuntu 10.04 by Martin Truebner */
901 if (rc == -1 && errno == 22) rc = 0;
902
903 if (rc < 0)
904 {
905 pDEVBLK->sense[0] = SENSE_EC;
906 *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
907 return;
908 }
909
910 // Adjust the residual byte count
911 *pResidual -= sSegLen;
912
913 // We are done if current segment satisfies CCW count
914 if( iPos + sSegLen == sCount )
915 {
916 *pResidual -= sSegLen;
917 *pUnitStat = CSW_CE | CSW_DE;
918 return;
919 }
920 }
921
922 // Set unit status and residual byte count
923 *pUnitStat = CSW_CE | CSW_DE;
924 *pResidual = 0;
925 }
926
927 // --------------------------------------------------------------------
928 // CTCI_ReadThread
929 // --------------------------------------------------------------------
930 //
931 // When an IP frame is received from the TUN/TAP interface, the frame
932 // is enqueued on the device frame buffer.
933 //
934 // The device frame buffer is a chain of blocks. The first 2 bytes of
935 // a block (CTCIHDR) specify the offset in the buffer of the next block.
936 // The final block in indicated by a CTCIHDR offset value of 0x0000.
937 //
938 // Within each block, each IP frame is preceeded by a segment header
939 // (CTCISEG). This segment header has a 2 byte length field that
940 // specifies the length of the segment (including the segment header),
941 // a 2 byte frame type field (always 0x0800 = IPv4), and a 2 byte
942 // reserved area (always 0000), followed by the actual frame data.
943 //
944 // The CTCI_ReadThread reads the IP frame, then CTCI_EnqueueIPFrame
945 // function is called to add it to the frame buffer (which precedes
946 // each one with a CTCISEG and adjusts the block header (CTCIHDR)
947 // offset value as appropriate.
948 //
949 // Oddly, it is the CTCI_Read function (called by CCW processing in
950 // response to a guest SIO request) that adds the CTCIHDR with the
951 // 000 offset value marking the end of the buffer's chain of blocks,
952 // and not the CTCI_EnqueueIPFrame nor the CTCI_ReadThread as would
953 // be expected.
954 //
955 // Also note that the iFrameOffset field in the CTCI device's CTCBLK
956 // control block is the offset from the end of the buffer's first
957 // CTCIHDR to where the end-of-chain CTCIHDR is, and is identical to
958 // all of the queued CTCISEG's hwLength fields added together.
959 //
960
CTCI_ReadThread(PCTCBLK pCTCBLK)961 static void* CTCI_ReadThread( PCTCBLK pCTCBLK )
962 {
963 DEVBLK* pDEVBLK = pCTCBLK->pDEVBLK[0];
964 int iLength;
965 BYTE szBuff[2048];
966
967 // ZZ FIXME: Try to avoid race condition at startup with hercifc
968 SLEEP(10);
969
970 pCTCBLK->pid = getpid();
971
972 while( pCTCBLK->fd != -1 && !pCTCBLK->fCloseInProgress )
973 {
974 // Read frame from the TUN/TAP interface
975 iLength = TUNTAP_Read( pCTCBLK->fd, szBuff, sizeof(szBuff) );
976
977 // Check for error condition
978 if( iLength < 0 )
979 {
980 logmsg( _("HHCCT048E %4.4X: Error reading from %s: %s\n"),
981 pDEVBLK->devnum, pCTCBLK->szTUNDevName,
982 strerror( errno ) );
983 break;
984 }
985
986 if( iLength == 0 ) // (probably EINTR; ignore)
987 continue;
988
989 if( pCTCBLK->fDebug )
990 {
991 logmsg( _("HHCCT049I %4.4X: Received packet from %s (%d bytes):\n"),
992 pDEVBLK->devnum, pCTCBLK->szTUNDevName, iLength );
993 packet_trace( szBuff, iLength );
994 }
995
996 // Enqueue frame on buffer, if buffer is full, keep trying
997 while( CTCI_EnqueueIPFrame( pDEVBLK, szBuff, iLength ) < 0
998 && pCTCBLK->fd != -1 && !pCTCBLK->fCloseInProgress )
999 {
1000 if( EMSGSIZE == errno ) // (if too large for buffer)
1001 {
1002 if( pCTCBLK->fDebug )
1003 logmsg( _("HHCCT072W %4.4X: Packet too big; dropped.\n"),
1004 pDEVBLK->devnum );
1005 break; // (discard it...)
1006 }
1007
1008 ASSERT( ENOBUFS == errno );
1009
1010 // Don't use sched_yield() here; use an actual non-dispatchable
1011 // delay instead so as to allow another [possibly lower priority]
1012 // thread to 'read' (remove) some packet(s) from our frame buffer.
1013 usleep( CTC_DELAY_USECS ); // (wait a bit before retrying...)
1014 }
1015 }
1016
1017 // We must do the close since we were the one doing the i/o...
1018
1019 VERIFY( pCTCBLK->fd == -1 || TUNTAP_Close( pCTCBLK->fd ) == 0 );
1020 pCTCBLK->fd = -1;
1021
1022 return NULL;
1023 }
1024
1025 // --------------------------------------------------------------------
1026 // CTCI_EnqueueIPFrame
1027 // --------------------------------------------------------------------
1028 //
1029 // Places the provided IP frame in the next available frame slot in
1030 // the adapter buffer. For details regarding the actual buffer layout
1031 // please refer to the comments preceding the CTCI_ReadThread function.
1032 //
1033 // Returns:
1034 //
1035 // 0 == Success
1036 // -1 == Failure; errno = ENOBUFS: No buffer space available
1037 // EMSGSIZE: Message too long
1038 //
CTCI_EnqueueIPFrame(DEVBLK * pDEVBLK,BYTE * pData,size_t iSize)1039 static int CTCI_EnqueueIPFrame( DEVBLK* pDEVBLK,
1040 BYTE* pData, size_t iSize )
1041 {
1042 PCTCIHDR pFrame;
1043 PCTCISEG pSegment;
1044 PCTCBLK pCTCBLK = (PCTCBLK)pDEVBLK->dev_data;
1045
1046 // Will frame NEVER fit into buffer??
1047 if( iSize > MAX_CTCI_FRAME_SIZE( pCTCBLK ) )
1048 {
1049 errno = EMSGSIZE; // Message too long
1050 return -1; // (-1==failure)
1051 }
1052
1053 obtain_lock( &pCTCBLK->Lock );
1054
1055 // Ensure we dont overflow the buffer
1056 if( ( pCTCBLK->iFrameOffset + // Current buffer Offset
1057 sizeof( CTCIHDR ) + // Size of Block Header
1058 sizeof( CTCISEG ) + // Size of Segment Header
1059 iSize + // Size of Ethernet packet
1060 sizeof(pFrame->hwOffset) ) // Size of Block terminator
1061 > pCTCBLK->iMaxFrameBufferSize ) // Size of Frame buffer
1062 {
1063 release_lock( &pCTCBLK->Lock );
1064 errno = ENOBUFS; // No buffer space available
1065 return -1; // (-1==failure)
1066 }
1067
1068 // Fix-up Frame pointer
1069 pFrame = (PCTCIHDR)pCTCBLK->bFrameBuffer;
1070
1071 // Fix-up Segment pointer
1072 pSegment = (PCTCISEG)( pCTCBLK->bFrameBuffer +
1073 sizeof( CTCIHDR ) +
1074 pCTCBLK->iFrameOffset );
1075
1076 // Initialize segment
1077 memset( pSegment, 0, iSize + sizeof( CTCISEG ) );
1078
1079 // Increment offset
1080 pCTCBLK->iFrameOffset += sizeof( CTCISEG ) + iSize;
1081
1082 // Update next frame offset
1083 STORE_HW( pFrame->hwOffset,
1084 pCTCBLK->iFrameOffset + sizeof( CTCIHDR ) );
1085
1086 // Store segment length
1087 STORE_HW( pSegment->hwLength, sizeof( CTCISEG ) + iSize );
1088
1089 // Store Frame type
1090 STORE_HW( pSegment->hwType, ETH_TYPE_IP );
1091
1092 // Copy data
1093 memcpy( pSegment->bData, pData, iSize );
1094
1095 // Mark data pending
1096 pCTCBLK->fDataPending = 1;
1097
1098 release_lock( &pCTCBLK->Lock );
1099
1100 obtain_lock( &pCTCBLK->EventLock );
1101 signal_condition( &pCTCBLK->Event );
1102 release_lock( &pCTCBLK->EventLock );
1103
1104 return 0; // (0==success)
1105 }
1106
1107 //
1108 // ParseArgs
1109 //
1110
ParseArgs(DEVBLK * pDEVBLK,PCTCBLK pCTCBLK,int argc,char ** argv)1111 static int ParseArgs( DEVBLK* pDEVBLK, PCTCBLK pCTCBLK,
1112 int argc, char** argv )
1113 {
1114 struct in_addr addr; // Work area for addresses
1115 int iMTU;
1116 int i;
1117 MAC mac; // Work area for MAC address
1118 #if defined(OPTION_W32_CTCI)
1119 int iKernBuff;
1120 int iIOBuff;
1121 #endif
1122
1123 // Housekeeping
1124 memset( &addr, 0, sizeof( struct in_addr ) );
1125 memset( &mac, 0, sizeof( MAC ) );
1126
1127 // Set some initial defaults
1128 strcpy( pCTCBLK->szMTU, "1500" );
1129 strcpy( pCTCBLK->szNetMask, "255.255.255.255" );
1130 #if defined( OPTION_W32_CTCI )
1131 strcpy( pCTCBLK->szTUNCharName, tt32_get_default_iface() );
1132 #else
1133 strcpy( pCTCBLK->szTUNCharName, HERCTUN_DEV );
1134 #endif
1135
1136 #if defined( OPTION_W32_CTCI )
1137 pCTCBLK->iKernBuff = DEF_CAPTURE_BUFFSIZE;
1138 pCTCBLK->iIOBuff = DEF_PACKET_BUFFSIZE;
1139 #endif
1140
1141 // Initialize getopt's counter. This is necessary in the case
1142 // that getopt was used previously for another device.
1143
1144 OPTRESET();
1145 optind = 0;
1146 // Check for correct number of arguments
1147 if( argc < 2 )
1148 {
1149 logmsg( _("HHCCT056E %4.4X: Incorrect number of parameters\n"),
1150 pDEVBLK->devnum );
1151 return -1;
1152 }
1153 // Compatability with old format configuration files needs to be
1154 // maintained. Old format statements have the tun character device
1155 // name as the second argument on Linux, or CTCI-W32 as the first
1156 // argument on Windows.
1157 if( ( strncasecmp( argv[0], "/", 1 ) == 0 ) ||
1158 ( strncasecmp( pDEVBLK->typname, "CTCI-W32", 8 ) == 0 ) )
1159 {
1160 pCTCBLK->fOldFormat = 1;
1161 }
1162 else
1163 {
1164 // Build new argv list.
1165 // getopt_long used to work on old format configuration statements
1166 // because LCS was the first argument passed to the device
1167 // initialization routine (and was interpreted by getopt*
1168 // as the program name and ignored). Now that argv[0] is a valid
1169 // argument, we need to shift the arguments and insert a dummy
1170 // argv[0];
1171
1172 // Don't allow us to exceed the allocated storage (sanity check)
1173 if( argc > (MAX_ARGS-1) )
1174 argc = (MAX_ARGS-1);
1175
1176 for( i = argc; i > 0; i-- )
1177 argv[i] = argv[i - 1];
1178
1179 argc++;
1180 argv[0] = pDEVBLK->typname;
1181 }
1182
1183 // Parse any optional arguments if not old format
1184 while( !pCTCBLK->fOldFormat )
1185 {
1186 int c;
1187
1188 #if defined(HAVE_GETOPT_LONG)
1189 int iOpt;
1190
1191 static struct option options[] =
1192 {
1193 { "dev", 1, NULL, 'n' },
1194 #if defined( OPTION_W32_CTCI )
1195 { "kbuff", 1, NULL, 'k' },
1196 { "ibuff", 1, NULL, 'i' },
1197 #endif
1198 { "mtu", 1, NULL, 't' },
1199 { "netmask", 1, NULL, 's' },
1200 { "mac", 1, NULL, 'm' },
1201 { "debug", 0, NULL, 'd' },
1202 { NULL, 0, NULL, 0 }
1203 };
1204
1205 c = getopt_long( argc, argv,
1206 "n"
1207 #if defined( OPTION_W32_CTCI )
1208 ":k:i"
1209 #endif
1210 ":t:s:m:d",
1211 options, &iOpt );
1212 #else /* defined(HAVE_GETOPT_LONG) */
1213 c = getopt( argc, argv, "n"
1214 #if defined( OPTION_W32_CTCI )
1215 ":k:i"
1216 #endif
1217 ":t:s:m:d");
1218 #endif /* defined(HAVE_GETOPT_LONG) */
1219
1220 if( c == -1 ) // No more options found
1221 break;
1222
1223 switch( c )
1224 {
1225 case 'n': // Network Device
1226 #if defined( OPTION_W32_CTCI )
1227 // This could be the IP or MAC address of the
1228 // host ethernet adapter.
1229 if( inet_aton( optarg, &addr ) == 0 )
1230 {
1231 // Not an IP address, check for valid MAC
1232 if( ParseMAC( optarg, mac ) != 0 )
1233 {
1234 logmsg( _("HHCCT050E %4.4X: Invalid adapter address %s\n"),
1235 pDEVBLK->devnum, optarg );
1236 return -1;
1237 }
1238 }
1239 #endif // defined( OPTION_W32_CTCI )
1240 // This is the file name of the special TUN/TAP character device
1241 if( strlen( optarg ) > sizeof( pCTCBLK->szTUNCharName ) - 1 )
1242 {
1243 logmsg( _("HHCCT051E %4.4X: Invalid device name %s\n"),
1244 pDEVBLK->devnum, optarg );
1245 return -1;
1246 }
1247 strcpy( pCTCBLK->szTUNCharName, optarg );
1248 break;
1249
1250 #if defined( OPTION_W32_CTCI )
1251 case 'k': // Kernel Buffer Size (Windows only)
1252 iKernBuff = atoi( optarg );
1253
1254 if( iKernBuff * 1024 < MIN_CAPTURE_BUFFSIZE ||
1255 iKernBuff * 1024 > MAX_CAPTURE_BUFFSIZE )
1256 {
1257 logmsg( _("HHCCT052E %4.4X: Invalid kernel buffer size %s\n"),
1258 pDEVBLK->devnum, optarg );
1259 return -1;
1260 }
1261
1262 pCTCBLK->iKernBuff = iKernBuff * 1024;
1263 break;
1264
1265 case 'i': // I/O Buffer Size (Windows only)
1266 iIOBuff = atoi( optarg );
1267
1268 if( iIOBuff * 1024 < MIN_PACKET_BUFFSIZE ||
1269 iIOBuff * 1024 > MAX_PACKET_BUFFSIZE )
1270 {
1271 logmsg( _("HHCCT053E %4.4X: Invalid DLL I/O buffer size %s\n"),
1272 pDEVBLK->devnum, optarg );
1273 return -1;
1274 }
1275
1276 pCTCBLK->iIOBuff = iIOBuff * 1024;
1277 break;
1278 #endif // defined( OPTION_W32_CTCI )
1279
1280 case 't': // MTU of point-to-point link (ignored if Windows)
1281 iMTU = atoi( optarg );
1282
1283 if( iMTU < 46 || iMTU > 65536 )
1284 {
1285 logmsg( _("HHCCT054E %4.4X: Invalid MTU size %s\n"),
1286 pDEVBLK->devnum, optarg );
1287 return -1;
1288 }
1289
1290 strcpy( pCTCBLK->szMTU, optarg );
1291 break;
1292
1293 case 's': // Netmask of point-to-point link
1294 if( inet_aton( optarg, &addr ) == 0 )
1295 {
1296 logmsg( _("HHCCT055E %4.4X: Invalid netmask %s\n"),
1297 pDEVBLK->devnum, optarg );
1298 return -1;
1299 }
1300
1301 strcpy( pCTCBLK->szNetMask, optarg );
1302 break;
1303
1304 case 'm':
1305 if( ParseMAC( optarg, mac ) != 0 )
1306 {
1307 logmsg( _("HHCCT056E %4.4X: Invalid MAC address %s\n"),
1308 pDEVBLK->devnum, optarg );
1309 return -1;
1310 }
1311
1312 strcpy( pCTCBLK->szMACAddress, optarg );
1313
1314 break;
1315
1316 case 'd': // Diagnostics
1317 pCTCBLK->fDebug = TRUE;
1318 break;
1319
1320 default:
1321 break;
1322 }
1323 }
1324
1325 // Shift past any options
1326 argc -= optind;
1327 argv += optind;
1328
1329 i = 0;
1330
1331 // Check for correct number of arguments
1332 if( argc == 0 )
1333 {
1334 logmsg( _("HHCCT056E %4.4X: Incorrect number of parameters\n"),
1335 pDEVBLK->devnum );
1336 return -1;
1337 }
1338
1339 if( !pCTCBLK->fOldFormat )
1340 {
1341 // New format has 2 and only 2 parameters (Though several options).
1342 if( argc != 2 )
1343 {
1344 logmsg( _("HHCCT057E %4.4X: Incorrect number of parameters\n"),
1345 pDEVBLK->devnum );
1346 return -1;
1347 }
1348
1349 // Guest IP Address
1350 if( inet_aton( *argv, &addr ) == 0 )
1351 {
1352 logmsg( _("HHCCT058E %4.4X: Invalid IP address %s\n"),
1353 pDEVBLK->devnum, *argv );
1354 return -1;
1355 }
1356
1357 strcpy( pCTCBLK->szGuestIPAddr, *argv );
1358
1359 argc--; argv++;
1360
1361 // Driver IP Address
1362 if( inet_aton( *argv, &addr ) == 0 )
1363 {
1364 logmsg( _("HHCCT059E %4.4X: Invalid IP address %s\n"),
1365 pDEVBLK->devnum, *argv );
1366 return -1;
1367 }
1368
1369 strcpy( pCTCBLK->szDriveIPAddr, *argv );
1370
1371 argc--; argv++;
1372 }
1373 else // if( pCTCBLK->fOldFormat )
1374 {
1375 #if !defined( OPTION_W32_CTCI )
1376 // All arguments are non-optional in linux old-format
1377 // Old format has 5 and only 5 arguments
1378 if( argc != 5 )
1379 {
1380 logmsg( _("HHCCT060E %4.4X: Incorrect number of parameters\n"),
1381 pDEVBLK->devnum );
1382 return -1;
1383 }
1384
1385 // TUN/TAP Device
1386 if( **argv != '/' ||
1387 strlen( *argv ) > sizeof( pCTCBLK->szTUNCharName ) - 1 )
1388 {
1389 logmsg( _("HHCCT061E %4.4X: invalid device name %s\n"),
1390 pDEVBLK->devnum, *argv );
1391 return -1;
1392 }
1393
1394 strcpy( pCTCBLK->szTUNCharName, *argv );
1395
1396 argc--; argv++;
1397
1398 // MTU Size
1399 iMTU = atoi( *argv );
1400
1401 if( iMTU < 46 || iMTU > 65536 )
1402 {
1403 logmsg( _("HHCCT062E %4.4X: Invalid MTU size %s\n"),
1404 pDEVBLK->devnum, *argv );
1405 return -1;
1406 }
1407
1408 strcpy( pCTCBLK->szMTU, *argv );
1409 argc--; argv++;
1410
1411 // Guest IP Address
1412 if( inet_aton( *argv, &addr ) == 0 )
1413 {
1414 logmsg( _("HHCCT063E %4.4X: Invalid IP address %s\n"),
1415 pDEVBLK->devnum, *argv );
1416 return -1;
1417 }
1418
1419 strcpy( pCTCBLK->szGuestIPAddr, *argv );
1420
1421 argc--; argv++;
1422
1423 // Driver IP Address
1424 if( inet_aton( *argv, &addr ) == 0 )
1425 {
1426 logmsg( _("HHCCT064E %4.4X: Invalid IP address %s\n"),
1427 pDEVBLK->devnum, *argv );
1428 return -1;
1429 }
1430
1431 strcpy( pCTCBLK->szDriveIPAddr, *argv );
1432
1433 argc--; argv++;
1434
1435 // Netmask
1436 if( inet_aton( *argv, &addr ) == 0 )
1437 {
1438 logmsg( _("HHCCT065E %4.4X: Invalid netmask %s\n"),
1439 pDEVBLK->devnum, *argv );
1440 return -1;
1441 }
1442
1443 strcpy( pCTCBLK->szNetMask, *argv );
1444
1445 argc--; argv++;
1446
1447 if( argc > 0 )
1448 {
1449 logmsg( _("HHCCT066E %4.4X: Incorrect number of parameters\n"),
1450 pDEVBLK->devnum );
1451 return -1;
1452 }
1453 #else // defined( OPTION_W32_CTCI )
1454 // There are 2 non-optional arguments in the Windows old-format:
1455 // Guest IP address and Gateway address.
1456 // There are also 2 additional optional arguments:
1457 // Kernel buffer size and I/O buffer size.
1458
1459 while( argc > 0 )
1460 {
1461 switch( i )
1462 {
1463 case 0: // Non-optional arguments
1464 // Guest IP Address
1465 if( inet_aton( *argv, &addr ) == 0 )
1466 {
1467 logmsg( _("HHCCT067E %4.4X: Invalid IP address %s\n"),
1468 pDEVBLK->devnum, *argv );
1469 return -1;
1470 }
1471
1472 strcpy( pCTCBLK->szGuestIPAddr, *argv );
1473
1474 argc--; argv++;
1475
1476 // Destination (Gateway) Address
1477 if( inet_aton( *argv, &addr ) == 0 )
1478 {
1479 // Not an IP address, check for valid MAC
1480 if( ParseMAC( *argv, mac ) != 0 )
1481 {
1482 logmsg( _("HHCCT068E %4.4X: Invalid MAC address %s\n"),
1483 pDEVBLK->devnum, *argv );
1484 return -1;
1485 }
1486 }
1487
1488 strcpy( pCTCBLK->szTUNCharName, *argv );
1489
1490 // Kludge: This may look strange at first, but with
1491 // TunTap32, only the last 3 bytes of the "driver IP
1492 // address" is actually used. It's purpose is to
1493 // generate a unique MAC for the virtual interface.
1494 // Thus, having the same address for the adapter and
1495 // destination is not an issue. This used to be
1496 // generated from the guest IP address, I screwed up
1497 // TunTap32 V2. (JAP)
1498 // This also fixes the confusing error messages from
1499 // TunTap.c when a MAC is given for this argument.
1500
1501 strcpy( pCTCBLK->szDriveIPAddr,
1502 pCTCBLK->szGuestIPAddr );
1503
1504 argc--; argv++; i++;
1505 continue;
1506
1507 case 1: // Optional arguments from here on:
1508 // Kernel Buffer Size
1509 iKernBuff = atoi( *argv );
1510
1511 if( iKernBuff * 1024 < MIN_CAPTURE_BUFFSIZE ||
1512 iKernBuff * 1024 > MAX_CAPTURE_BUFFSIZE )
1513 {
1514 logmsg( _("HHCCT069E %4.4X: Invalid kernel buffer size %s\n"),
1515 pDEVBLK->devnum, *argv );
1516 return -1;
1517 }
1518
1519 pCTCBLK->iKernBuff = iKernBuff * 1024;
1520
1521 argc--; argv++; i++;
1522 continue;
1523
1524 case 2:
1525 // I/O Buffer Size
1526 iIOBuff = atoi( *argv );
1527
1528 if( iIOBuff * 1024 < MIN_PACKET_BUFFSIZE ||
1529 iIOBuff * 1024 > MAX_PACKET_BUFFSIZE )
1530 {
1531 logmsg( _("HHCCT070E %4.4X: Invalid DLL I/O buffer size %s\n"),
1532 pDEVBLK->devnum, *argv );
1533 return -1;
1534 }
1535
1536 pCTCBLK->iIOBuff = iIOBuff * 1024;
1537
1538 argc--; argv++; i++;
1539 continue;
1540
1541 default:
1542 logmsg( _("HHCCT071E %4.4X: Incorrect number of parameters\n"),
1543 pDEVBLK->devnum );
1544 return -1;
1545 }
1546 }
1547 #endif // !defined( OPTION_W32_CTCI )
1548 }
1549
1550 return 0;
1551 }
1552 #endif /* !defined(__SOLARIS__) jbs */
1553