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