1 /* SHARED.C     (c) Copyright Greg Smith, 2002-2009                  */
2 /*              Shared Device Server                                 */
3 
4 #include "hstdinc.h"
5 
6 #define _HERCULES_SHARED_C
7 #define _SHARED_C_
8 #define _HDASD_DLL_
9 #include "hercules.h"
10 #include "opcode.h"
11 #include "devtype.h"
12 
13 #define FBA_BLKGRP_SIZE (120*512)
14 
15 /* Change the following to "define" when Shared FBA support is implemented */
16 #undef FBA_SHARED
17 
18 /*-------------------------------------------------------------------*/
19 /* Definitions for sense data format codes and message codes         */
20 /*-------------------------------------------------------------------*/
21 #define FORMAT_0                0       /* Program or System Checks  */
22 #define FORMAT_1                1       /* Device Equipment Checks   */
23 #define FORMAT_2                2       /* 3990 Equipment Checks     */
24 #define FORMAT_3                3       /* 3990 Control Checks       */
25 #define FORMAT_4                4       /* Data Checks               */
26 #define FORMAT_5                5       /* Data Check + Displacement */
27 #define FORMAT_6                6       /* Usage Stats/Overrun Errors*/
28 #define FORMAT_7                7       /* Device Control Checks     */
29 #define FORMAT_8                8       /* Device Equipment Checks   */
30 #define FORMAT_9                9       /* Device Rd/Wrt/Seek Checks */
31 #define FORMAT_F                15      /* Cache Storage Checks      */
32 #define MESSAGE_0               0       /* Message 0                 */
33 #define MESSAGE_1               1       /* Message 1                 */
34 #define MESSAGE_2               2       /* Message 2                 */
35 #define MESSAGE_3               3       /* Message 3                 */
36 #define MESSAGE_4               4       /* Message 4                 */
37 #define MESSAGE_5               5       /* Message 5                 */
38 #define MESSAGE_6               6       /* Message 6                 */
39 #define MESSAGE_7               7       /* Message 7                 */
40 #define MESSAGE_8               8       /* Message 8                 */
41 #define MESSAGE_9               9       /* Message 9                 */
42 #define MESSAGE_A               10      /* Message A                 */
43 #define MESSAGE_B               11      /* Message B                 */
44 #define MESSAGE_C               12      /* Message C                 */
45 #define MESSAGE_D               13      /* Message D                 */
46 #define MESSAGE_E               14      /* Message E                 */
47 #define MESSAGE_F               15      /* Message F                 */
48 
49 #if defined(OPTION_SHARED_DEVICES)
50 
51 DEVHND  shared_ckd_device_hndinfo;
52 DEVHND  shared_fba_device_hndinfo;
53 
54 static  BYTE eighthexFF[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
55 
56 /*-------------------------------------------------------------------
57  * Update notify - called by device handlers for sharable devices
58  *-------------------------------------------------------------------*/
shared_update_notify(DEVBLK * dev,int block)59 int shared_update_notify (DEVBLK *dev, int block)
60 {
61 int      i, j;                          /* Indexes                   */
62 
63     /* Return if no remotes are connected */
64     if (dev->shrdconn == 0)
65         return 0;
66 
67     for (i = 0; i < SHARED_MAX_SYS; i++)
68     {
69 
70         /* Ignore the entry if it doesn't exist or if it's ours
71            our if it's already maxed out */
72         if (dev->shrd[i] == NULL || dev->shrd[i]->id == dev->ioactive
73          || dev->shrd[i]->purgen < 0)
74             continue;
75 
76         /* Check if the block is already entered */
77         for (j = 0; j < dev->shrd[i]->purgen; j++)
78             if (fetch_fw(dev->shrd[i]->purge[j]) == (U32)block) break;
79 
80         /* Add the block if it's not already there */
81         if (j >= dev->shrd[i]->purgen)
82         {
83             if (dev->shrd[i]->purgen >= SHARED_PURGE_MAX)
84                 dev->shrd[i]->purgen = -1;
85             else
86                 store_fw (dev->shrd[i]->purge[dev->shrd[i]->purgen++],
87                           block);
88            shrdtrc(dev,"notify %d added for id=%d, n=%d\n",
89                    block, dev->shrd[i]->id, dev->shrd[i]->purgen);
90         }
91 
92     } /* for each possible remote system */
93 
94     return 0;
95 
96 } /* shared_update_notify */
97 
98 
99 /*-------------------------------------------------------------------
100  * CKD init exit (client side)
101  *-------------------------------------------------------------------*/
shared_ckd_init(DEVBLK * dev,int argc,char * argv[])102 int shared_ckd_init (DEVBLK *dev, int argc, char *argv[] )
103 {
104 int      rc;                            /* Return code               */
105 int      i;                             /* Loop index                */
106 int      retry;                         /* 1=Connection being retried*/
107 char    *ipname;                        /* Remote name or address    */
108 char    *port = NULL;                   /* Remote port               */
109 char    *rmtnum = NULL;                 /* Remote device number      */
110 struct   hostent *he;                   /* -> hostent structure      */
111 char    *kw;                            /* Argument keyword          */
112 char    *op;                            /* Argument operand          */
113 BYTE     c;                             /* Used for parsing          */
114 char    *cu = NULL;                     /* Specified control unit    */
115 FWORD    cyls;                          /* Remote number cylinders   */
116 char    *p, buf[1024];                  /* Work buffer               */
117 
118     retry = dev->connecting;
119 
120     /* Process the arguments */
121     if (!retry)
122     {
123         if (argc < 1 || strlen(argv[0]) >= sizeof(buf))
124             return -1;
125         strcpy (buf, argv[0]);
126 
127         /* First argument is `ipname:port:devnum' */
128         ipname = buf;
129         if (strchr(ipname,'/') || strchr(ipname,'\\'))
130             return -1;
131         p = strchr (buf, ':');
132         if (p)
133         {
134             *p = '\0';
135             port = p + 1;
136             p = strchr (port, ':');
137         }
138         if (p)
139         {
140             *p = '\0';
141             rmtnum = p + 1;
142         }
143 
144 #if defined( HAVE_SYS_UN_H )
145         if ( strcmp (ipname, "localhost") == 0)
146             dev->localhost = 1;
147         else
148 #endif
149         {
150             if ( (he = gethostbyname (ipname)) == NULL )
151                 return -1;
152             memcpy(&dev->rmtaddr, he->h_addr_list[0], sizeof(dev->rmtaddr));
153         }
154 
155         if (port && strlen(port))
156         {
157             if (sscanf(port, "%hu%c", &dev->rmtport, &c) != 1)
158                 return -1;
159         }
160         else
161             dev->rmtport = SHARED_DEFAULT_PORT;
162 
163         if (rmtnum && strlen(rmtnum))
164         {
165             if (strlen (rmtnum) > 4
166              || sscanf (rmtnum, "%hx%c", &dev->rmtnum, &c) != 1)
167                 return -1;
168         }
169         else
170             dev->rmtnum = dev->devnum;
171 
172         /* Process the remaining arguments */
173         for (i = 1; i < argc; i++)
174         {
175             if (strcasecmp ("readonly", argv[i]) == 0 ||
176                 strcasecmp ("rdonly",   argv[i]) == 0 ||
177                 strcasecmp ("ro",       argv[i]) == 0)
178             {
179                 dev->ckdrdonly = 1;
180                 continue;
181             }
182             if (strcasecmp ("fakewrite", argv[i]) == 0 ||
183                 strcasecmp ("fakewrt",   argv[i]) == 0 ||
184                 strcasecmp ("fw",        argv[i]) == 0)
185             {
186                 dev->ckdfakewr = 1;
187                 continue;
188             }
189             if (strlen (argv[i]) > 3
190              && memcmp("cu=", argv[i], 3) == 0)
191             {
192                 kw = strtok (argv[i], "=");
193                 op = strtok (NULL, " \t");
194                 cu = op;
195                 continue;
196             }
197 #ifdef HAVE_LIBZ
198             if (strlen (argv[i]) > 5
199              && memcmp("comp=", argv[i], 5) == 0)
200             {
201                 kw = strtok (argv[i], "=");
202                 op = strtok (NULL, " \t");
203                 dev->rmtcomp = atoi (op);
204                 if (dev->rmtcomp < 0 || dev->rmtcomp > 9)
205                     dev->rmtcomp = 0;
206                 continue;
207             }
208 #endif
209             logmsg (_("HHCSH001S parameter %d is invalid: %s\n"),
210                     i + 1, argv[i]);
211             return -1;
212         }
213     }
214 
215     /* Set suported compression */
216     dev->rmtcomps = 0;
217 #ifdef HAVE_LIBZ
218     dev->rmtcomps |= SHRD_LIBZ;
219 #endif
220 #ifdef CCKD_BZIP2
221     dev->rmtcomps |= SHRD_BZIP2;
222 #endif
223 
224     /* Update the device handler vector */
225     dev->hnd = &shared_ckd_device_hndinfo;
226 
227     dev->connecting = 1;
228 
229 init_retry:
230 
231     do {
232         rc = clientConnect (dev, retry);
233         if (rc < 0)
234         {
235             logmsg (_("HHCSH002W %4.4X connect pending to %s\n"),
236                     dev->devnum, dev->filename);
237             if (retry) SLEEP(5);
238         }
239     } while (retry && rc < 0);
240 
241     /* Return if unable to connect */
242     if (rc < 0) return 0;
243 
244     dev->ckdnumfd = 1;
245     dev->ckdfd[0] = dev->fd;
246 
247     /* Get the number of cylinders */
248     rc = clientRequest (dev, cyls, 4, SHRD_QUERY, SHRD_CKDCYLS, NULL, NULL);
249     if (rc < 0)
250         goto init_retry;
251     else if (rc != 4)
252     {
253         logmsg (_("HHCSH003S %4.4X Error retrieving cylinders\n"),
254                 dev->devnum);
255         return -1;
256     }
257     dev->ckdcyls = fetch_fw (cyls);
258 
259     /* Get the device characteristics */
260     rc = clientRequest (dev, dev->devchar, sizeof(dev->devchar),
261                         SHRD_QUERY, SHRD_DEVCHAR, NULL, NULL);
262     if (rc < 0)
263         goto init_retry;
264     else if (rc == 0 || rc > (int)sizeof(dev->devchar))
265     {
266         logmsg (_("HHCSH004S %4.4X Error retrieving device"
267                   " characteristics\n"), dev->devnum);
268         return -1;
269     }
270     dev->numdevchar = rc;
271 
272     /* Get number of heads from devchar */
273     dev->ckdheads = fetch_hw (dev->devchar + 14);
274 
275     /* Calculate number of tracks */
276     dev->ckdtrks = dev->ckdcyls * dev->ckdheads;
277     dev->ckdhitrk[0] = dev->ckdtrks;
278 
279     /* Check the device type */
280     if (dev->devtype == 0)
281         dev->devtype = fetch_hw (dev->devchar + 3);
282     else if (dev->devtype != fetch_hw (dev->devchar + 3))
283     {
284         logmsg (_("HHCSH005S %4.4X Remote device %4.4X is a %4.4X\n"),
285                 dev->devnum, dev->rmtnum, fetch_hw (dev->devchar + 3));
286         return -1;
287     }
288 
289     /* Get the device id */
290     rc = clientRequest (dev, dev->devid, sizeof(dev->devid),
291                         SHRD_QUERY, SHRD_DEVID, NULL, NULL);
292     if (rc < 0)
293         goto init_retry;
294     else if (rc == 0 || rc > (int)sizeof(dev->devid))
295     {
296         logmsg (_("HHCSH006S %4.4X Error retrieving device id\n"),
297                 dev->devnum);
298         return -1;
299     }
300     dev->numdevid = rc;
301 
302     /* Indicate no active track */
303     dev->cache = dev->bufcur = -1;
304     dev->buf = NULL;
305 
306     /* Set number of sense bytes */
307     dev->numsense = 32;
308 
309     /* Locate the CKD dasd table entry */
310     dev->ckdtab = dasd_lookup (DASD_CKDDEV, NULL, dev->devtype, dev->ckdcyls);
311     if (dev->ckdtab == NULL)
312     {
313         logmsg (_("HHCSH007S %4.4X device type %4.4X not found in dasd table\n"),
314                 dev->devnum, dev->devtype);
315         return -1;
316     }
317 
318     /* Set the track size */
319     dev->ckdtrksz = (dev->ckdtab->r1 + 511) & ~511;
320 
321     /* Locate the CKD control unit dasd table entry */
322     dev->ckdcu = dasd_lookup (DASD_CKDCU, cu ? cu : dev->ckdtab->cu, 0, 0);
323     if (dev->ckdcu == NULL)
324     {
325         logmsg (_("HHCSH008S %4.4X control unit %s not found in dasd table\n"),
326                 dev->devnum, cu ? cu : dev->ckdtab->cu);
327         return -1;
328     }
329 
330     /* Set flag bit if 3990 controller */
331     if (dev->ckdcu->devt == 0x3990)
332         dev->ckd3990 = 1;
333 
334     /* Clear the DPA */
335     memset(dev->pgid, 0, sizeof(dev->pgid));
336 
337     /* Request the channel to merge data chained write CCWs into
338        a single buffer before passing data to the device handler */
339     dev->cdwmerge = 1;
340 
341     /* Purge the cache */
342     clientPurge (dev, 0, NULL);
343 
344     /* Log the device geometry */
345     if (!dev->batch)
346     logmsg (_("HHCSH009I %s cyls=%d heads=%d tracks=%d trklen=%d\n"),
347             dev->filename, dev->ckdcyls,
348             dev->ckdheads, dev->ckdtrks, dev->ckdtrksz);
349 
350     dev->connecting = 0;
351 
352     return 0;
353 } /* shared_ckd_init */
354 
355 /*-------------------------------------------------------------------
356  * CKD close exit (client side)
357  *-------------------------------------------------------------------*/
shared_ckd_close(DEVBLK * dev)358 static int shared_ckd_close ( DEVBLK *dev )
359 {
360     /* Purge the cached entries */
361     clientPurge (dev, 0, NULL);
362 
363     /* Disconnect and close */
364     if (dev->fd >= 0)
365     {
366         clientRequest (dev, NULL, 0, SHRD_DISCONNECT, 0, NULL, NULL);
367         close_socket (dev->fd);
368         dev->fd = -1;
369     }
370 
371     return 0;
372 } /* shared_ckd_close */
373 
374 /*-------------------------------------------------------------------
375  * FBA init exit (client side)
376  *-------------------------------------------------------------------*/
shared_fba_init(DEVBLK * dev,int argc,char * argv[])377 int shared_fba_init (DEVBLK *dev, int argc, char *argv[] )
378 {
379 int      rc;                            /* Return code               */
380 int      i;                             /* Loop index                */
381 int      retry;                         /* 1=Connection being retried*/
382 char    *ipname;                        /* Remote name or address    */
383 char    *port = NULL;                   /* Remote port               */
384 char    *rmtnum = NULL;                 /* Remote device number      */
385 struct   hostent *he;                   /* -> hostent structure      */
386 char    *kw;                            /* Argument keyword          */
387 char    *op;                            /* Argument operand          */
388 char     c;                             /* Work for sscanf           */
389 FWORD    origin;                        /* FBA origin                */
390 FWORD    numblks;                       /* FBA number blocks         */
391 FWORD    blksiz;                        /* FBA block size            */
392 char    *p, buf[1024];                  /* Work buffer               */
393 
394     retry = dev->connecting;
395 
396     /* Process the arguments */
397     if (!retry)
398     {
399 
400         kw = op = NULL;
401 
402         if (argc < 1 || strlen(argv[0]) >= sizeof(buf))
403             return -1;
404         strcpy (buf, argv[0]);
405 
406         /* First argument is `ipname:port:devnum' */
407         ipname = buf;
408         p = strchr (buf, ':');
409         if (p)
410         {
411             *p = '\0';
412             port = p + 1;
413             p = strchr (port, ':');
414         }
415         if (p)
416         {
417             *p = '\0';
418             rmtnum = p + 1;
419         }
420 
421         if ( (he = gethostbyname (ipname)) == NULL )
422             return -1;
423         memcpy(&dev->rmtaddr, he->h_addr_list[0], sizeof(dev->rmtaddr));
424 
425         if (port)
426         {
427             if (sscanf(port, "%hu%c", &dev->rmtport, &c) != 1)
428                 return -1;
429         }
430         else
431             dev->rmtport = SHARED_DEFAULT_PORT;
432 
433         if (rmtnum)
434         {
435             if (strlen (rmtnum) > 4
436              || sscanf (rmtnum, "%hx%c", &dev->rmtnum, &c) != 0)
437                 return -1;
438         }
439         else
440             dev->rmtnum = dev->devnum;
441 
442         /* Process the remaining arguments */
443         for (i = 1; i < argc; i++)
444         {
445 #ifdef HAVE_LIBZ
446             if (strlen (argv[i]) > 5
447              && memcmp("comp=", argv[i], 5) == 0)
448             {
449                 kw = strtok (argv[i], "=");
450                 op = strtok (NULL, " \t");
451                 dev->rmtcomp = atoi (op);
452                 if (dev->rmtcomp < 0 || dev->rmtcomp > 9)
453                     dev->rmtcomp = 0;
454                 continue;
455             }
456 #endif
457             logmsg (_("HHCSH010S parameter %d is invalid: %s\n"),
458                     i + 1, argv[i]);
459             return -1;
460         }
461     }
462 
463     /* Set suported compression */
464     dev->rmtcomps = 0;
465 #ifdef HAVE_LIBZ
466     dev->rmtcomps |= SHRD_LIBZ;
467 #endif
468 #ifdef CCKD_BZIP2
469     dev->rmtcomps |= SHRD_BZIP2;
470 #endif
471 
472     /* Update the device handler vector */
473     dev->hnd = &shared_fba_device_hndinfo;
474 
475     dev->connecting = 1;
476 
477 init_retry:
478 
479     do {
480         rc = clientConnect (dev, retry);
481         if (rc < 0)
482         {
483             logmsg (_("HHCSH011I %4.4X connect pending to %s\n"),
484                     dev->devnum, dev->filename);
485             if (retry) SLEEP(5);
486         }
487     } while (retry && rc < 0);
488 
489     /* Return if unable to connect */
490     if (rc < 0) return 0;
491 
492     /* Get the fba origin */
493     rc = clientRequest (dev, origin, 4, SHRD_QUERY, SHRD_FBAORIGIN, NULL, NULL);
494     if (rc < 0)
495         goto init_retry;
496     else if (rc != 4)
497     {
498         logmsg (_("HHCSH012S %4.4X Error retrieving fba origin\n"),
499                 dev->devnum);
500         return -1;
501     }
502     dev->fbaorigin = fetch_fw (origin);
503 
504     /* Get the number of blocks */
505     rc = clientRequest (dev, numblks, 4, SHRD_QUERY, SHRD_FBANUMBLK, NULL, NULL);
506     if (rc < 0)
507         goto init_retry;
508     else if (rc != 4)
509     {
510         logmsg (_("HHCSH013S %4.4X Error retrieving fba number blocks\n"),
511                 dev->devnum);
512         return -1;
513     }
514     dev->fbanumblk = fetch_fw (numblks);
515 
516     /* Get the block size */
517     rc = clientRequest (dev, blksiz, 4, SHRD_QUERY, SHRD_FBABLKSIZ, NULL, NULL);
518     if (rc < 0)
519         goto init_retry;
520     else if (rc != 4)
521     {
522         logmsg (_("HHCSH014S %4.4X Error retrieving fba block size\n"),
523                 dev->devnum);
524         return -1;
525     }
526     dev->fbablksiz = fetch_fw (blksiz);
527     dev->fbaend = (dev->fbaorigin + dev->fbanumblk) * dev->fbablksiz;
528 
529     /* Get the device id */
530     rc = clientRequest (dev, dev->devid, sizeof(dev->devid),
531                         SHRD_QUERY, SHRD_DEVID, NULL, NULL);
532     if (rc < 0)
533         goto init_retry;
534     else if (rc == 0 || rc > (int)sizeof(dev->devid))
535     {
536         logmsg (_("HHCSH015S %4.4X Error retrieving device id\n"),
537                 dev->devnum);
538         return -1;
539     }
540     dev->numdevid = rc;
541 
542     /* Check the device type */
543     if (dev->devtype != fetch_hw (dev->devid + 4))
544     {
545         logmsg (_("HHCSH016S %4.4X Remote device %4.4X is a %4.4X\n"),
546                 dev->devnum, dev->rmtnum, fetch_hw (dev->devid + 4));
547         return -1;
548     }
549 
550     /* Get the device characteristics */
551     rc = clientRequest (dev, dev->devchar, sizeof(dev->devchar),
552                         SHRD_QUERY, SHRD_DEVCHAR, NULL, NULL);
553     if (rc < 0)
554         goto init_retry;
555     else if (rc == 0 || rc > (int)sizeof(dev->devchar))
556     {
557         logmsg (_("HHCSH017S %4.4X Error retrieving device"
558                   " characteristics\n"), dev->devnum);
559         return -1;
560     }
561     dev->numdevchar = rc;
562 
563     /* Indicate no active track */
564     dev->cache = dev->bufcur = -1;
565     dev->buf = NULL;
566 
567     /* Set number of sense bytes */
568     dev->numsense = 32;
569 
570     /* Locate the FBA dasd table entry */
571     dev->fbatab = dasd_lookup (DASD_FBADEV, NULL, dev->devtype, dev->fbanumblk);
572     if (dev->fbatab == NULL)
573     {
574         logmsg (_("HHCSH018S %4.4X device type %4.4X not found in dasd table\n"),
575                 dev->devnum, dev->devtype);
576         return -1;
577     }
578 
579     /* Purge the cache */
580     clientPurge (dev, 0, NULL);
581 
582     /* Log the device geometry */
583     logmsg (_("HHCSH019I %s origin=%d blks=%d\n"),
584             dev->filename, dev->fbaorigin, dev->fbanumblk);
585 
586     dev->connecting = 0;
587 
588     return 0;
589 }
590 
591 /*-------------------------------------------------------------------
592  * FBA close exit (client side)
593  *-------------------------------------------------------------------*/
shared_fba_close(DEVBLK * dev)594 static int shared_fba_close (DEVBLK *dev)
595 {
596     /* Purge the cached entries */
597     clientPurge (dev, 0, NULL);
598 
599     /* Disconnect and close */
600     if (dev->fd >= 0)
601     {
602         clientRequest (dev, NULL, 0, SHRD_DISCONNECT, 0, NULL, NULL);
603         close_socket (dev->fd);
604         dev->fd = -1;
605     }
606 
607     return 0;
608 }
609 
610 /*-------------------------------------------------------------------
611  * Start I/O exit (client side)
612  *-------------------------------------------------------------------*/
shared_start(DEVBLK * dev)613 static void shared_start(DEVBLK *dev)
614 {
615 int      rc;                            /* Return code               */
616 U16      devnum;                        /* Cache device number       */
617 int      trk;                           /* Cache track number        */
618 int      code;                          /* Response code             */
619 BYTE     buf[SHARED_PURGE_MAX * 4];     /* Purge list                */
620 
621     shrdtrc(dev,"start cur %d cache %d\n",dev->bufcur,dev->cache);
622 
623     /* Send the START request */
624     rc = clientRequest (dev, buf, sizeof(buf),
625                         SHRD_START, 0, &code, NULL);
626     if (rc < 0)
627     {
628         logmsg(_("HHCSH020E %4.4X error during channel program start\n"),
629                dev->devnum);
630         clientPurge (dev, 0, NULL);
631         dev->cache = dev->bufcur = -1;
632         dev->buf = NULL;
633         return;
634     }
635 
636     /* Check for purge */
637     if (code & SHRD_PURGE)
638     {
639         if (rc / 4 > SHARED_PURGE_MAX) rc = 0;
640         clientPurge (dev, rc / 4, buf);
641     }
642 
643     /* Make previous active entry active again */
644     if (dev->cache >= 0)
645     {
646         cache_lock (CACHE_DEVBUF);
647         SHRD_CACHE_GETKEY (dev->cache, devnum, trk);
648         if (dev->devnum == devnum && dev->bufcur == trk)
649             cache_setflag(CACHE_DEVBUF, dev->cache, ~0, SHRD_CACHE_ACTIVE);
650         else
651         {
652             dev->cache = dev->bufcur = -1;
653             dev->buf = NULL;
654         }
655         cache_unlock (CACHE_DEVBUF);
656     }
657 } /* shared_start */
658 
659 /*-------------------------------------------------------------------
660  * End I/O exit (client side)
661  *-------------------------------------------------------------------*/
shared_end(DEVBLK * dev)662 static void shared_end (DEVBLK *dev)
663 {
664 int      rc;                            /* Return code               */
665 
666     shrdtrc(dev,"end cur %d cache %d\n",dev->bufcur,dev->cache);
667 
668     /* Write the previous active entry if it was updated */
669     if (dev->bufupd)
670         clientWrite (dev, dev->bufcur);
671     dev->bufupd = 0;
672 
673     /* Mark the active entry inactive */
674     if (dev->cache >= 0)
675     {
676         cache_lock (CACHE_DEVBUF);
677         cache_setflag (CACHE_DEVBUF, dev->cache, ~SHRD_CACHE_ACTIVE, 0);
678         cache_unlock (CACHE_DEVBUF);
679     }
680 
681     /* Send the END request */
682     rc = clientRequest (dev, NULL, 0, SHRD_END, 0, NULL, NULL);
683     if (rc < 0)
684     {
685         logmsg(_("HHCSH021E %4.4X error during channel program end\n"),
686                dev->devnum);
687         clientPurge (dev, 0, NULL);
688         dev->cache = dev->bufcur = -1;
689         dev->buf = NULL;
690         return;
691     }
692 } /* shared_end */
693 
694 /*-------------------------------------------------------------------
695  * Shared ckd read track exit (client side)
696  *-------------------------------------------------------------------*/
shared_ckd_read(DEVBLK * dev,int trk,BYTE * unitstat)697 static int shared_ckd_read (DEVBLK *dev, int trk, BYTE *unitstat)
698 {
699 int      rc;                            /* Return code               */
700 int      retries = 10;                  /* Number read retries       */
701 int      cache;                         /* Lookup index              */
702 int      lru;                           /* Available index           */
703 int      len;                           /* Response length           */
704 int      id;                            /* Response id               */
705 BYTE    *buf;                           /* Cache buffer              */
706 BYTE     code;                          /* Response code             */
707 U16      devnum;                        /* Response device number    */
708 BYTE     hdr[SHRD_HDR_SIZE + 4];        /* Read request header       */
709 
710     /* Initialize the unit status */
711     *unitstat = 0;
712 
713     /* Return if reading the same track image */
714     if (trk == dev->bufcur && dev->cache >= 0)
715     {
716         dev->bufoff = 0;
717         dev->bufoffhi = dev->ckdtrksz;
718         return 0;
719     }
720 
721     shrdtrc(dev,"ckd_read trk %d\n",trk);
722 
723     /* Write the previous active entry if it was updated */
724     if (dev->bufupd)
725         clientWrite (dev, dev->bufcur);
726     dev->bufupd = 0;
727 
728     /* Reset buffer offsets */
729     dev->bufoff = 0;
730     dev->bufoffhi = dev->ckdtrksz;
731 
732     cache_lock (CACHE_DEVBUF);
733 
734     /* Inactivate the previous image */
735     if (dev->cache >= 0)
736         cache_setflag (CACHE_DEVBUF, dev->cache, ~SHRD_CACHE_ACTIVE, 0);
737     dev->cache = dev->bufcur = -1;
738 
739 cache_retry:
740 
741     /* Lookup the track in the cache */
742     cache = cache_lookup (CACHE_DEVBUF, SHRD_CACHE_SETKEY(dev->devnum, trk), &lru);
743 
744     /* Process cache hit */
745     if (cache >= 0)
746     {
747         cache_setflag (CACHE_DEVBUF, cache, ~0, SHRD_CACHE_ACTIVE);
748         cache_unlock (CACHE_DEVBUF);
749         dev->cachehits++;
750         dev->cache = cache;
751         dev->buf = cache_getbuf (CACHE_DEVBUF, cache, 0);
752         dev->bufcur = trk;
753         dev->bufoff = 0;
754         dev->bufoffhi = dev->ckdtrksz;
755         dev->buflen = shared_ckd_trklen (dev, dev->buf);
756         dev->bufsize = cache_getlen (CACHE_DEVBUF, cache);
757         shrdtrc(dev,"ckd_read trk %d cache hit %d\n",trk,dev->cache);
758         return 0;
759     }
760 
761     /* Special processing if no available cache entry */
762     if (lru < 0)
763     {
764         shrdtrc(dev,"ckd_read trk %d cache wait\n",trk);
765         dev->cachewaits++;
766         cache_wait (CACHE_DEVBUF);
767         goto cache_retry;
768     }
769 
770     /* Process cache miss */
771     shrdtrc(dev,"ckd_read trk %d cache miss %d\n",trk,dev->cache);
772     dev->cachemisses++;
773     cache_setflag (CACHE_DEVBUF, lru, 0, SHRD_CACHE_ACTIVE|DEVBUF_TYPE_SCKD);
774     cache_setkey (CACHE_DEVBUF, lru, SHRD_CACHE_SETKEY(dev->devnum, trk));
775     cache_setage (CACHE_DEVBUF, lru);
776     buf = cache_getbuf (CACHE_DEVBUF, lru, dev->ckdtrksz);
777 
778     cache_unlock (CACHE_DEVBUF);
779 
780 read_retry:
781 
782     /* Send the read request for the track to the remote host */
783     SHRD_SET_HDR (hdr, SHRD_READ, 0, dev->rmtnum, dev->rmtid, 4);
784     store_fw (hdr + SHRD_HDR_SIZE, trk);
785     rc = clientSend (dev, hdr, NULL, 0);
786     if (rc < 0)
787     {
788         ckd_build_sense (dev, SENSE_EC, 0, 0, FORMAT_1, MESSAGE_0);
789         *unitstat = CSW_CE | CSW_DE | CSW_UC;
790         logmsg(_("HHCSH022E %4.4X error reading track %d\n"), dev->devnum, trk);
791         return -1;
792     }
793 
794     /* Read the track from the remote host */
795     rc = clientRecv (dev, hdr, buf, dev->ckdtrksz);
796     SHRD_GET_HDR (hdr, code, *unitstat, devnum, id, len);
797     if (rc < 0 || code & SHRD_ERROR)
798     {
799         if (rc < 0 && retries--) goto read_retry;
800         ckd_build_sense (dev, SENSE_EC, 0, 0, FORMAT_1, MESSAGE_0);
801         *unitstat = CSW_CE | CSW_DE | CSW_UC;
802         logmsg(_("HHCSH023E %4.4X error reading track %d\n"),
803                dev->devnum, trk);
804         return -1;
805     }
806 
807     /* Read the sense data if an i/o error occurred */
808     if (code & SHRD_IOERR)
809         clientRequest (dev, dev->sense, dev->numsense,
810                       SHRD_SENSE, 0, NULL, NULL);
811 
812     /* Read complete */
813     dev->cache = lru;
814     dev->buf = cache_getbuf (CACHE_DEVBUF, lru, 0);
815     dev->bufcur = trk;
816     dev->bufoff = 0;
817     dev->bufoffhi = dev->ckdtrksz;
818     dev->buflen = shared_ckd_trklen (dev, dev->buf);
819     dev->bufsize = cache_getlen (CACHE_DEVBUF, lru);
820     dev->buf[0] = 0;
821 
822     return 0;
823 } /* shared_ckd_read */
824 
825 /*-------------------------------------------------------------------
826  * Shared ckd write track exit (client side)
827  *-------------------------------------------------------------------*/
shared_ckd_write(DEVBLK * dev,int trk,int off,BYTE * buf,int len,BYTE * unitstat)828 static int shared_ckd_write (DEVBLK *dev, int trk, int off,
829                              BYTE *buf, int len, BYTE *unitstat)
830 {
831 int      rc;                            /* Return code               */
832 
833     /* Immediately return if fake writing */
834     if (dev->ckdfakewr)
835         return len;
836 
837     /* Error if opened read-only */
838     if (dev->ckdrdonly)
839     {
840         ckd_build_sense (dev, SENSE_EC, SENSE1_WRI, 0,
841                         FORMAT_1, MESSAGE_0);
842         *unitstat = CSW_CE | CSW_DE | CSW_UC;
843         return -1;
844     }
845 
846     shrdtrc(dev,"ckd_write trk %d off %d len %d\n",trk,off,len);
847 
848     /* If the track is not current then read it */
849     if (trk != dev->bufcur)
850     {
851         rc = (dev->hnd->read) (dev, trk, unitstat);
852         if (rc < 0)
853         {
854             dev->bufcur = dev->cache = -1;
855             return -1;
856         }
857     }
858 
859     /* Invalid track format if going past buffer end */
860     if (off + len > dev->bufoffhi)
861     {
862         ckd_build_sense (dev, 0, SENSE1_ITF, 0, 0, 0);
863         *unitstat = CSW_CE | CSW_DE | CSW_UC;
864         return -1;
865     }
866 
867     /* Copy the data into the buffer */
868     if (buf) memcpy (dev->buf + off, buf, len);
869 
870     /* Set low and high updated offsets */
871     if (!dev->bufupd || off < dev->bufupdlo)
872         dev->bufupdlo = off;
873     if (dev->bufoff + len > dev->bufupdhi)
874         dev->bufupdhi = off + len;
875 
876     /* Indicate track image has been modified */
877     if (!dev->bufupd)
878     {
879         dev->bufupd = 1;
880         shared_update_notify (dev, trk);
881     }
882 
883     return len;
884 } /* shared_ckd_write */
885 
886 /*-------------------------------------------------------------------
887  * Return track image length
888  *-------------------------------------------------------------------*/
shared_ckd_trklen(DEVBLK * dev,BYTE * buf)889 static int shared_ckd_trklen (DEVBLK *dev, BYTE *buf)
890 {
891 int             sz;                     /* Size so far               */
892 
893     for (sz = CKDDASD_TRKHDR_SIZE;
894          memcmp (buf + sz, &eighthexFF, 8) != 0; )
895     {
896         /* add length of count, key, and data fields */
897         sz += CKDDASD_RECHDR_SIZE +
898                 buf[sz+5] +
899                 (buf[sz+6] << 8) + buf[sz+7];
900         if (sz > dev->ckdtrksz - 8) break;
901     }
902 
903     /* add length for end-of-track indicator */
904     sz += CKDDASD_RECHDR_SIZE;
905 
906     if (sz > dev->ckdtrksz)
907         sz = dev->ckdtrksz;
908 
909     return sz;
910 }
911 
912 #if defined(FBA_SHARED)
913 /*-------------------------------------------------------------------
914  * Shared fba read block exit (client side)
915  *-------------------------------------------------------------------*/
shared_fba_read(DEVBLK * dev,int blkgrp,BYTE * unitstat)916 static int shared_fba_read (DEVBLK *dev, int blkgrp, BYTE *unitstat)
917 {
918 int      rc;                            /* Return code               */
919 int      retries = 10;                  /* Number read retries       */
920 int      i, o;                          /* Cache indexes             */
921 BYTE     code;                          /* Response code             */
922 U16      devnum;                        /* Response device number    */
923 int      len;                           /* Response length           */
924 int      id;                            /* Response id               */
925 BYTE     hdr[SHRD_HDR_SIZE + 4];        /* Read request header       */
926 
927 
928     /* Return if reading the same block group */
929     if (blkgrp >= 0 && blkgrp == dev->bufcur)
930         return 0;
931 
932     shrdtrc(dev,"fba_read blkrp %d\n",blkgrp);
933 
934     /* Write the previous active entry if it was updated */
935     if (dev->bufupd)
936         clientWrite (dev, dev->bufcur);
937     dev->bufupd = 0;
938 
939     /* Reset buffer offsets */
940     dev->bufoff = 0;
941     dev->bufoffhi = FBA_BLKGRP_SIZE;
942 
943     cache_lock (CACHE_DEVBUF);
944 
945     /* Make the previous cache entry inactive */
946     if (dev->cache >= 0)
947         cache_setflag(CACHE_DEVBUF, dev->cache, ~FBA_CACHE_ACTIVE, 0);
948     dev->bufcur = dev->cache = -1;
949 
950 cache_retry:
951 
952     /* Search the cache */
953     i = cache_lookup (CACHE_DEVBUF, FBA_CACHE_SETKEY(dev->devnum, blkgrp), &o);
954 
955     /* Cache hit */
956     if (i >= 0)
957     {
958         cache_setflag(CACHE_DEVBUF, dev->cache, ~0, FBA_CACHE_ACTIVE);
959         cache_setage(CACHE_DEVBUF, dev->cache);
960         cache_unlock(CACHE_DEVBUF);
961         dev->cachehits++;
962         dev->cache = i;
963         dev->buf = cache_getbuf(CACHE_DEVBUF, dev->cache, 0);
964         dev->bufcur = blkgrp;
965         dev->bufoff = 0;
966         dev->bufoffhi = shared_fba_blkgrp_len (dev, blkgrp);
967         dev->buflen = shared_fba_blkgrp_len (dev, blkgrp);
968         dev->bufsize = cache_getlen(CACHE_DEVBUF, dev->cache);
969         shrdtrc(dev,"fba_read blkgrp %d cache hit %d\n",blkgrp,dev->cache);
970         return 0;
971     }
972 
973     /* Wait if no available cache entry */
974     if (o < 0)
975     {
976         shrdtrc(dev,"fba_read blkgrp %d cache wait\n",blkgrp);
977         dev->cachewaits++;
978         cache_wait(CACHE_DEVBUF);
979         goto cache_retry;
980     }
981 
982     /* Cache miss */
983     shrdtrc(dev,"fba_read blkgrp %d cache miss %d\n",blkgrp,dev->cache);
984     dev->cachemisses++;
985     cache_setflag(CACHE_DEVBUF, o, 0, FBA_CACHE_ACTIVE|DEVBUF_TYPE_SFBA);
986     cache_setkey (CACHE_DEVBUF, o, FBA_CACHE_SETKEY(dev->devnum, blkgrp));
987     cache_setage (CACHE_DEVBUF, o);
988     dev->buf = cache_getbuf(CACHE_DEVBUF, o, FBA_BLKGRP_SIZE);
989 
990     cache_unlock (CACHE_DEVBUF);
991 
992 read_retry:
993 
994     /* Send the read request for the blkgrp to the remote host */
995     SHRD_SET_HDR (hdr, SHRD_READ, 0, dev->rmtnum, dev->rmtid, 4);
996     store_fw (hdr + SHRD_HDR_SIZE, blkgrp);
997     rc = clientSend (dev, hdr, NULL, 0);
998     if (rc < 0)
999     {
1000         dev->sense[0] = SENSE_EC;
1001         *unitstat = CSW_CE | CSW_DE | CSW_UC;
1002         logmsg(_("HHCSH024E %4.4X error reading block group %d\n"),
1003                dev->devnum, blkgrp);
1004         return -1;
1005     }
1006 
1007     /* Read the blkgrp from the remote host */
1008     rc = clientRecv (dev, hdr, dev->buf, FBA_BLKGRP_SIZE);
1009     SHRD_GET_HDR (hdr, code, *unitstat, devnum, id, len);
1010     if (rc < 0 || code & SHRD_ERROR)
1011     {
1012         if (rc < 0 && retries--) goto read_retry;
1013         dev->sense[0] = SENSE_EC;
1014         *unitstat = CSW_CE | CSW_DE | CSW_UC;
1015         logmsg(_("HHCSH025E %4.4X error reading block group %d\n"),
1016                dev->devnum, blkgrp);
1017         return -1;
1018     }
1019 
1020     /* Read the sense data if an i/o error occurred */
1021     if (code & SHRD_IOERR)
1022         clientRequest (dev, dev->sense, dev->numsense,
1023                       SHRD_SENSE, 0, NULL, NULL);
1024 
1025     dev->cache = o;
1026     dev->buf = cache_getbuf(CACHE_DEVBUF, dev->cache, 0);
1027     dev->buf[0] = 0;
1028     dev->bufcur = blkgrp;
1029     dev->bufoff = 0;
1030     dev->bufoffhi = shared_fba_blkgrp_len (dev, blkgrp);
1031     dev->buflen = shared_fba_blkgrp_len (dev, blkgrp);
1032     dev->bufsize = cache_getlen(CACHE_DEVBUF, dev->cache);
1033 
1034     return 0;
1035 }
1036 
1037 /*-------------------------------------------------------------------
1038  * Shared fba write block exit (client side)
1039  *-------------------------------------------------------------------*/
shared_fba_write(DEVBLK * dev,int blkgrp,int off,BYTE * buf,int len,BYTE * unitstat)1040 static int shared_fba_write (DEVBLK *dev, int blkgrp, int off,
1041                              BYTE *buf, int len, BYTE *unitstat)
1042 {
1043 int             rc;                     /* Return code               */
1044 
1045     /* Read the block group */
1046     if (blkgrp != dev->bufcur)
1047     {
1048         rc = (dev->hnd->read) (dev, blkgrp, unitstat);
1049         if (rc < 0) {
1050             dev->bufcur = dev->cache = -1;
1051             return -1;
1052         }
1053     }
1054 
1055     /* Copy to the device buffer */
1056     if (buf) memcpy (dev->buf + off, buf, len);
1057 
1058     /* Update high/low offsets */
1059     if (!dev->bufupd || off < dev->bufupdlo)
1060         dev->bufupdlo = off;
1061     if (off + len > dev-> bufupdhi)
1062         dev->bufupdhi = off + len;
1063 
1064     /* Indicate block group has been modified */
1065     if (!dev->bufupd)
1066     {
1067         dev->bufupd = 1;
1068         shared_update_notify (dev, blkgrp);
1069     }
1070 
1071     return len;
1072 }
1073 
1074 
1075 /*-------------------------------------------------------------------*/
1076 /* Calculate length of an FBA block group                            */
1077 /*-------------------------------------------------------------------*/
shared_fba_blkgrp_len(DEVBLK * dev,int blkgrp)1078 static int shared_fba_blkgrp_len (DEVBLK *dev, int blkgrp)
1079 {
1080 off_t   offset;                         /* Offset of block group     */
1081 
1082     offset = blkgrp * FBA_BLKGRP_SIZE;
1083     if (dev->fbaend - offset < FBA_BLKGRP_SIZE)
1084         return (int)(dev->fbaend - offset);
1085     else
1086         return FBA_BLKGRP_SIZE;
1087 }
1088 
1089 #endif /* FBA_SHARED */
1090 
1091 /*-------------------------------------------------------------------
1092  * Shared usage exit (client side)
1093  *-------------------------------------------------------------------*/
shared_used(DEVBLK * dev)1094 static int shared_used (DEVBLK *dev)
1095 {
1096 int      rc;                            /* Return code               */
1097 FWORD    usage;                         /* Usage buffer              */
1098 
1099     /* Get usage information */
1100     rc = clientRequest (dev, usage, 4, SHRD_USED, 0, NULL, NULL);
1101     if (rc != 4)
1102     {
1103         logmsg (_("HHCSH026E %4.4X Error retrieving usage information\n"),
1104                 dev->devnum);
1105         return -1;
1106     }
1107     return fetch_fw (usage);
1108 } /* shared_used */
1109 
1110 /*-------------------------------------------------------------------
1111  * Shared reserve exit (client side)
1112  *-------------------------------------------------------------------*/
shared_reserve(DEVBLK * dev)1113 static void shared_reserve (DEVBLK *dev)
1114 {
1115 int      rc;                            /* Return code               */
1116 
1117     /* Issue reserve request */
1118     rc = clientRequest (dev, NULL, 0, SHRD_RESERVE, 0, NULL, NULL);
1119 
1120 } /* shared_reserve */
1121 
1122 /*-------------------------------------------------------------------
1123  * Shared release exit (client side)
1124  *-------------------------------------------------------------------*/
shared_release(DEVBLK * dev)1125 static void shared_release (DEVBLK *dev)
1126 {
1127 int      rc;                            /* Return code               */
1128 
1129     /* Issue release request */
1130     rc = clientRequest (dev, NULL, 0, SHRD_RELEASE, 0, NULL, NULL);
1131 
1132 } /* shared_release */
1133 
1134 /*-------------------------------------------------------------------
1135  * Write to host
1136  *
1137  * NOTE - writes are deferred until a switch occurs or the
1138  *        channel program ends.  We are called from either the
1139  *        read exit or the end channel program exit.
1140  *-------------------------------------------------------------------*/
clientWrite(DEVBLK * dev,int block)1141 static int clientWrite (DEVBLK *dev, int block)
1142 {
1143 int         rc;                         /* Return code               */
1144 int         retries = 10;               /* Number write retries      */
1145 int         len;                        /* Data length               */
1146 BYTE        hdr[SHRD_HDR_SIZE + 2 + 4]; /* Write header              */
1147 BYTE        code;                       /* Response code             */
1148 int         status;                     /* Response status           */
1149 int         id;                         /* Response identifier       */
1150 U16         devnum;                     /* Response device number    */
1151 BYTE        errmsg[SHARED_MAX_MSGLEN+1];/* Error message             */
1152 
1153     /* Calculate length to write */
1154     len = dev->bufupdhi - dev->bufupdlo;
1155     if (len <= 0 || dev->bufcur < 0)
1156     {
1157         dev->bufupdlo = dev->bufupdhi = 0;
1158         return 0;
1159     }
1160 
1161     shrdtrc(dev,"write rcd %d off %d len %d\n",block,dev->bufupdlo,len);
1162 
1163 write_retry:
1164 
1165     /* The write request contains a 2 byte offset and 4 byte id,
1166        followed by the data */
1167     SHRD_SET_HDR (hdr, SHRD_WRITE, 0, dev->rmtnum, dev->rmtid, len + 6);
1168     store_hw (hdr + SHRD_HDR_SIZE, dev->bufupdlo);
1169     store_fw (hdr + SHRD_HDR_SIZE + 2, block);
1170 
1171     rc = clientSend (dev, hdr, dev->buf + dev->bufupdlo, len);
1172     if (rc < 0)
1173     {
1174         logmsg(_("HHCSH027E %4.4X error writing track %d\n"),
1175              dev->devnum, dev->bufcur);
1176         dev->bufupdlo = dev->bufupdhi = 0;
1177         clientPurge (dev, 0, NULL);
1178         return -1;
1179     }
1180 
1181     /* Get the response */
1182     rc = clientRecv (dev, hdr, errmsg, sizeof(errmsg));
1183     SHRD_GET_HDR (hdr, code, status, devnum, id, len);
1184     if (rc < 0 || (code & SHRD_ERROR) || (code & SHRD_IOERR))
1185     {
1186         if (rc < 0 && retries--) goto write_retry;
1187         logmsg(_("HHCSH028E %4.4X remote error writing track %d: "
1188          "%2.2X-%2.2X\n"), dev->devnum, dev->bufcur, code, status);
1189         dev->bufupdlo = dev->bufupdhi = 0;
1190         clientPurge (dev, 0, NULL);
1191         return -1;
1192     }
1193 
1194     dev->bufupdlo = dev->bufupdhi = 0;
1195     return rc;
1196 } /* clientWrite */
1197 
1198 /*-------------------------------------------------------------------
1199  * Purge cache entries (client side)
1200  *-------------------------------------------------------------------*/
clientPurge(DEVBLK * dev,int n,void * buf)1201 static void clientPurge (DEVBLK *dev, int n, void *buf)
1202 {
1203     cache_lock(CACHE_DEVBUF);
1204     dev->rmtpurgen = n;
1205     dev->rmtpurge = (FWORD *)buf;
1206     cache_scan (CACHE_DEVBUF, clientPurgescan, dev);
1207     cache_unlock(CACHE_DEVBUF);
1208 }
clientPurgescan(int * answer,int ix,int i,void * data)1209 static int clientPurgescan (int *answer, int ix, int i, void *data)
1210 {
1211 U16             devnum;                 /* Cached device number      */
1212 int             trk;                    /* Cached track              */
1213 int             p;                      /* Purge index               */
1214 DEVBLK         *dev = data;             /* -> device block           */
1215 
1216     UNREFERENCED(answer);
1217     SHRD_CACHE_GETKEY(i, devnum, trk);
1218     if (devnum == dev->devnum)
1219     {
1220         if (dev->rmtpurgen == 0) {
1221             cache_release (ix, i, 0);
1222             shrdtrc(dev,"purge %d\n",trk);
1223         }
1224         else
1225         {
1226             for (p = 0; p < dev->rmtpurgen; p++)
1227             {
1228                 if (trk == (int)fetch_fw (dev->rmtpurge[p]))
1229                 {
1230                     shrdtrc(dev,"purge %d\n",trk);
1231                     cache_release (ix, i, 0);
1232                     break;
1233                 }
1234             }
1235         }
1236     }
1237     return 0;
1238 } /* clientPurge */
1239 
1240 /*-------------------------------------------------------------------
1241  * Connect to the server (client side)
1242  *-------------------------------------------------------------------*/
clientConnect(DEVBLK * dev,int retry)1243 static int clientConnect (DEVBLK *dev, int retry)
1244 {
1245 int                rc;                  /* Return code               */
1246 struct sockaddr   *server;              /* -> server descriptor      */
1247 int                flag;                /* Flags (version | release) */
1248 int                len;                 /* Length server descriptor  */
1249 struct sockaddr_in iserver;             /* inet server descriptor    */
1250 #if defined( HAVE_SYS_UN_H )
1251 struct sockaddr_un userver;             /* unix server descriptor    */
1252 #endif
1253 int                retries = 10;        /* Number of retries         */
1254 HWORD              id;                  /* Returned identifier       */
1255 HWORD              comp;                /* Returned compression parm */
1256 
1257     do {
1258 
1259         /* Close previous connection */
1260         if (dev->fd >= 0) close_socket (dev->fd);
1261 
1262         /* Get a socket */
1263         if (dev->localhost)
1264         {
1265 #if defined( HAVE_SYS_UN_H )
1266             dev->fd = dev->ckdfd[0] = socket (AF_UNIX, SOCK_STREAM, 0);
1267 #else // !defined( HAVE_SYS_UN_H )
1268             dev->fd = dev->ckdfd[0] = -1;
1269 #endif // defined( HAVE_SYS_UN_H )
1270             if (dev->fd < 0)
1271             {
1272                 logmsg (_("HHCSH029E %4.4X socket failed: %s\n"),
1273                         dev->devnum, strerror(HSO_errno));
1274                 return -1;
1275             }
1276 #if defined( HAVE_SYS_UN_H )
1277             userver.sun_family = AF_UNIX;
1278             sprintf(userver.sun_path, "/tmp/hercules_shared.%d", dev->rmtport);
1279             server = (struct sockaddr *)&userver;
1280             len = sizeof(userver);
1281 #endif // !defined( HAVE_SYS_UN_H )
1282         }
1283         else
1284         {
1285             dev->fd = dev->ckdfd[0] = socket (AF_INET, SOCK_STREAM, 0);
1286             if (dev->fd < 0)
1287             {
1288                 logmsg (_("HHCSH030E %4.4X socket failed: %s\n"),
1289                         dev->devnum, strerror(HSO_errno));
1290                 return -1;
1291             }
1292             iserver.sin_family      = AF_INET;
1293             iserver.sin_port        = htons(dev->rmtport);
1294             memcpy(&iserver.sin_addr.s_addr,&dev->rmtaddr,sizeof(struct in_addr));
1295             server = (struct sockaddr *)&iserver;
1296             len = sizeof(iserver);
1297         }
1298 
1299         /* Connect to the server */
1300         store_hw (id, dev->rmtid);
1301         rc = connect (dev->fd, server, len);
1302         shrdtrc(dev,"connect rc=%d errno=%d\n",rc, HSO_errno);
1303         if (rc >= 0)
1304         {
1305             if (!dev->batch)
1306               logmsg(_("HHCSH031I %4.4X Connected to %s\n"),
1307                  dev->devnum, dev->filename);
1308 
1309             /* Request device connection */
1310             flag = (SHARED_VERSION << 4) | SHARED_RELEASE;
1311             rc = clientRequest (dev, id, 2, SHRD_CONNECT, flag, NULL, &flag);
1312             if (rc >= 0)
1313             {
1314                 dev->rmtid = fetch_hw (id);
1315                 dev->rmtrel = flag & 0x0f;
1316             }
1317 
1318             /*
1319              * Negotiate compression - top 4 bits have the compression
1320              * algorithms we support (00010000 -> libz; 00100000 ->bzip2,
1321              * 00110000 -> both) and the bottom 4 bits indicates the
1322              * libz parm we want to use when sending data back & forth.
1323              * If the server returns `0' back, then we won't use libz to
1324              * compress data to the server.  What the `compression
1325              * algorithms we support' means is that if the data source is
1326              * cckd or cfba then the server doesn't have to uncompress
1327              * the data for us if we support the compression algorithm.
1328              */
1329 
1330             if (rc >= 0 && (dev->rmtcomp || dev->rmtcomps))
1331             {
1332                 rc = clientRequest (dev, comp, 2, SHRD_COMPRESS,
1333                            (dev->rmtcomps << 4) | dev->rmtcomp, NULL, NULL);
1334                 if (rc >= 0)
1335                     dev->rmtcomp = fetch_hw (comp);
1336             }
1337 
1338         }
1339         else if (!retry)
1340             logmsg(_("HHCSH032E %4.4X Connect %s %d: %s\n"),
1341                dev->devnum, dev->filename, HSO_errno, strerror(HSO_errno));
1342 
1343         if (rc < 0 && retry) usleep (20000);
1344 
1345     } while (retry && retries-- && rc < 0);
1346 
1347     return rc;
1348 
1349 } /* clientConnect */
1350 
1351 /*-------------------------------------------------------------------
1352  * Send request to host and get the response
1353  *
1354  * No data is sent on the request, buf gets the response.
1355  * If an uncorrectable connection error occurs -1 is returned.
1356  * Otherwise *code and *status is set from the response header
1357  *
1358  * Since `buf' may be NULL or not very long, response data is
1359  * received in a temporary buffer.  This enables us to receive
1360  * an error message from the remote system.
1361  *-------------------------------------------------------------------*/
clientRequest(DEVBLK * dev,BYTE * buf,int len,int cmd,int flags,int * code,int * status)1362 static int clientRequest (DEVBLK *dev, BYTE *buf, int len, int cmd,
1363                           int flags, int *code, int *status)
1364 {
1365 int      rc;                            /* Return code               */
1366 int      retries = 10;                  /* Number retries            */
1367 BYTE     rcode;                         /* Request return code       */
1368 BYTE     rstatus;                       /* Request return status     */
1369 U16      rdevnum;                       /* Request return devnum     */
1370 int      rid;                           /* Request return id         */
1371 int      rlen;                          /* Request return length     */
1372 BYTE     hdr[SHRD_HDR_SIZE];            /* Header                    */
1373 BYTE     temp[256];                     /* Temporary buffer          */
1374 
1375 retry :
1376 
1377     /* Send the request */
1378     SHRD_SET_HDR(hdr, cmd, flags, dev->rmtnum, dev->rmtid, 0);
1379     shrdtrc(dev,"client_request %2.2x %2.2x %2.2x %d\n",
1380             cmd,flags,dev->rmtnum,dev->rmtid);
1381     rc = clientSend (dev, hdr, NULL, 0);
1382     if (rc < 0) return rc;
1383 
1384     /* Receive the response */
1385     rc = clientRecv (dev, hdr, temp, sizeof(temp));
1386 
1387     /* Retry recv errors */
1388     if (rc < 0)
1389     {
1390         if (cmd != SHRD_CONNECT && retries--)
1391         {
1392             SLEEP (1);
1393             clientConnect (dev, 1);
1394             goto retry;
1395         }
1396         return -1;
1397     }
1398 
1399     /* Set code and status */
1400     SHRD_GET_HDR(hdr, rcode, rstatus, rdevnum, rid, rlen);
1401     shrdtrc(dev,"client_response %2.2x %2.2x %2.2x %d %d\n",
1402             rcode,rstatus,rdevnum,rid,rlen);
1403     if (code)   *code   = rcode;
1404     if (status) *status = rstatus;
1405 
1406     /* Copy the data into the caller's buffer */
1407     if (buf && len > 0 && rlen > 0)
1408         memcpy (buf, temp, len < rlen ? len : rlen);
1409 
1410     return rlen;
1411 } /* clientRequest */
1412 
1413 /*-------------------------------------------------------------------
1414  * Send a request to the host
1415  *
1416  * `buf' may be NULL
1417  * `buflen' is the length in `buf' (should be 0 if `buf' is NULL)
1418  * `hdr' may contain additional data; this is detected by the
1419  *       difference between `buflen' and the length in the header
1420  *
1421  * If `buf' is adjacent to `hdr' then `buf' should be NULL
1422  *
1423  *-------------------------------------------------------------------*/
clientSend(DEVBLK * dev,BYTE * hdr,BYTE * buf,int buflen)1424 static int clientSend (DEVBLK *dev, BYTE *hdr, BYTE *buf, int buflen)
1425 {
1426 int      rc;                            /* Return code               */
1427 BYTE     cmd;                           /* Header command            */
1428 BYTE     flag;                          /* Header flags              */
1429 U16      devnum;                        /* Header device nu          */
1430 int      len;                           /* Header length             */
1431 int      id;                            /* Header identifier         */
1432 int      hdrlen;                        /* Header length + other data*/
1433 int      off;                           /* Offset to buffer data     */
1434 BYTE    *sendbuf;                       /* Send buffer               */
1435 int      sendlen;                       /* Send length               */
1436 BYTE     cbuf[SHRD_HDR_SIZE + 65536];   /* Combined buffer           */
1437 
1438     /* Make buf, buflen consistent if no additional data to be sent  */
1439     if (buf == NULL) buflen = 0;
1440     else if (buflen == 0) buf = NULL;
1441 
1442     /* Calculate length of header, may contain additional data */
1443     SHRD_GET_HDR(hdr, cmd, flag, devnum, id, len);
1444     shrdtrc(dev,"client_send %2.2x %2.2x %2.2x %d %d\n",
1445              cmd,flag,devnum,id,len);
1446     hdrlen = SHRD_HDR_SIZE + (len - buflen);
1447     off = len - buflen;
1448 
1449     if (dev->fd < 0)
1450     {
1451         rc = clientConnect (dev, 1);
1452         if (rc < 0) return -1;
1453     }
1454 
1455 #ifdef HAVE_LIBZ
1456     /* Compress the buf */
1457     if (dev->rmtcomp != 0
1458      && flag == 0 && off <= SHRD_COMP_MAX_OFF
1459      && buflen >= SHARED_COMPRESS_MINLEN)
1460     {
1461         unsigned long newlen;
1462         newlen = 65536 - hdrlen;
1463         memcpy (cbuf, hdr, hdrlen);
1464         rc = compress2 (cbuf + hdrlen, &newlen,
1465                         buf, buflen, dev->rmtcomp);
1466         if (rc == Z_OK && (int)newlen < buflen)
1467         {
1468             cmd |= SHRD_COMP;
1469             flag = (SHRD_LIBZ << 4) | off;
1470             hdr = cbuf;
1471             hdrlen += newlen;
1472             buf = NULL;
1473             buflen = 0;
1474         }
1475     }
1476 #endif
1477 
1478     /* Combine header and data unless there's no buffer */
1479     if (buflen == 0)
1480     {
1481         sendbuf = hdr;
1482         sendlen = hdrlen;
1483     }
1484     else
1485     {
1486         memcpy (cbuf, hdr, hdrlen);
1487         memcpy (cbuf + hdrlen, buf, buflen);
1488         sendbuf = cbuf;
1489         sendlen = hdrlen + buflen;
1490     }
1491 
1492     SHRD_SET_HDR(sendbuf, cmd, flag, devnum, id, (U16)(sendlen - SHRD_HDR_SIZE));
1493 
1494     if (cmd & SHRD_COMP)
1495         shrdtrc(dev,"client_send %2.2x %2.2x %2.2x %d %d (compressed)\n",
1496                 cmd, flag, devnum, id, (int)(sendlen - SHRD_HDR_SIZE));
1497 
1498 retry:
1499 
1500     /* Send the header and data */
1501     rc = send (dev->fd, sendbuf, sendlen, 0);
1502     if (rc < 0)
1503     {
1504         rc = clientConnect (dev, 0);
1505         if (rc >= 0) goto retry;
1506     }
1507 
1508     /* Process return code */
1509     if (rc < 0)
1510     {
1511         logmsg(_("HHCSH033E %4.4X send error %d for %2.2X-%2.2X: %s\n"),
1512                dev->devnum, HSO_errno, cmd, flag, strerror(HSO_errno));
1513         return -1;
1514     }
1515 
1516     return rc;
1517 
1518 } /* clientSend */
1519 
1520 /*-------------------------------------------------------------------
1521  * Receive a response (client side)
1522  *-------------------------------------------------------------------*/
clientRecv(DEVBLK * dev,BYTE * hdr,BYTE * buf,int buflen)1523 static int clientRecv (DEVBLK *dev, BYTE *hdr, BYTE *buf, int buflen)
1524 {
1525 int      rc;                            /* Return code               */
1526 BYTE     code;                          /* Response code             */
1527 BYTE     status;                        /* Response status           */
1528 U16      devnum;                        /* Response device number    */
1529 int      id;                            /* Response identifier       */
1530 int      len;                           /* Response length           */
1531 
1532     /* Clear the header to zeroes */
1533     memset (hdr, 0, SHRD_HDR_SIZE);
1534 
1535     /* Return error if not connected */
1536     if (dev->fd < 0)
1537     {
1538         logmsg(_("HHCSH034E %4.4X Not connected to %s\n"),
1539                dev->devnum, dev->filename);
1540         return -1;
1541     }
1542 
1543     /* Receive the header */
1544     rc = recvData (dev->fd, hdr, buf, buflen, 0);
1545     if (rc < 0)
1546     {
1547         if (rc != -ENOTCONN)
1548             logmsg(_("HHCSH035E %4.4X recv error %d: %s\n"),
1549                    dev->devnum, -rc, strerror(-rc));
1550         return rc;
1551     }
1552     SHRD_GET_HDR(hdr, code, status, devnum, id, len);
1553 
1554     shrdtrc(dev,"client_recv %2.2x %2.2x %2.2x %d %d\n",
1555              code,status,devnum,id,len);
1556 
1557     /* Handle remote logical error */
1558     if (code & SHRD_ERROR)
1559     {
1560         logmsg(_("HHCSH036E %4.4X Remote error %2.2X-%2.2X: %s\n"),
1561                dev->devnum, code, status, buf);
1562         len = 0;
1563     }
1564 
1565     /* Reset code/status if response was compressed */
1566     if (len > 0 && code == SHRD_COMP)
1567     {
1568         code = SHRD_OK;
1569         status = 0;
1570     }
1571 
1572     /* Reset the header */
1573     SHRD_SET_HDR(hdr, code, status, devnum, id, len);
1574 
1575     return len;
1576 } /* clientRecv */
1577 
1578 /*-------------------------------------------------------------------
1579  * Receive data (server or client)
1580  *-------------------------------------------------------------------*/
recvData(int sock,BYTE * hdr,BYTE * buf,int buflen,int server)1581 static int recvData(int sock, BYTE *hdr, BYTE *buf, int buflen, int server)
1582 {
1583 int                     rc;             /* Return code               */
1584 int                     rlen;           /* Data length to recv       */
1585 int                     recvlen;        /* Total length              */
1586 BYTE                   *recvbuf;        /* Receive buffer            */
1587 BYTE                    cmd;            /* Header command            */
1588 BYTE                    flag;           /* Header flags              */
1589 U16                     devnum;         /* Header device number      */
1590 int                     id;             /* Header identifier         */
1591 int                     len;            /* Header length             */
1592 int                     comp = 0;       /* Compression type          */
1593 int                     off = 0;        /* Offset to compressed data */
1594 DEVBLK                 *dev = NULL;     /* For `shrdtrc'             */
1595 BYTE                    cbuf[65536];    /* Compressed buffer         */
1596 
1597 
1598     /* Receive the header */
1599     for (recvlen = 0; recvlen < (int)SHRD_HDR_SIZE; recvlen += rc)
1600     {
1601         rc = recv (sock, hdr + recvlen, SHRD_HDR_SIZE - recvlen, 0);
1602         if (rc < 0)
1603             return -HSO_errno;
1604         else if (rc == 0)
1605             return -HSO_ENOTCONN;
1606     }
1607     SHRD_GET_HDR (hdr, cmd, flag, devnum, id, len);
1608 
1609     shrdtrc(dev,"recvData    %2.2x %2.2x %2.2x %d %d\n",
1610              cmd, flag, devnum, id, len);
1611 
1612     /* Return if no data */
1613     if (len == 0) return 0;
1614 
1615     /* Check for compressed data */
1616     if ((server && (cmd & SHRD_COMP))
1617      || (!server && cmd == SHRD_COMP))
1618     {
1619         comp = (flag & SHRD_COMP_MASK) >> 4;
1620         off = flag & SHRD_COMP_OFF;
1621         cmd &= ~SHRD_COMP;
1622         flag = 0;
1623         recvbuf = cbuf;
1624         rlen = len;
1625     }
1626     else
1627     {
1628         recvbuf = buf;
1629         rlen = buflen < len ? buflen : len;
1630     }
1631 
1632     /* Receive the data */
1633     for (recvlen = 0; recvlen < rlen; recvlen += rc)
1634     {
1635         rc = recv (sock, recvbuf + recvlen, len - recvlen, 0);
1636         if (rc < 0)
1637             return -HSO_errno;
1638         else if (rc == 0)
1639             return -HSO_ENOTCONN;
1640     }
1641 
1642     /* Flush any remaining data */
1643     for (; rlen < len; rlen += rc)
1644     {
1645         BYTE buf[256];
1646         rc = recv (sock, buf, len - rlen < 256 ? len - rlen : 256, 0);
1647         if (rc < 0)
1648             return -HSO_errno;
1649         else if (rc == 0)
1650             return -HSO_ENOTCONN;
1651     }
1652 
1653     /* Check for compression */
1654     if (comp == SHRD_LIBZ) {
1655 #ifdef HAVE_LIBZ
1656         unsigned long newlen;
1657 
1658         if (off > 0)
1659             memcpy (buf, cbuf, off);
1660         newlen = buflen - off;
1661         rc = uncompress(buf + off, &newlen, cbuf + off, len - off);
1662         if (rc == Z_OK)
1663             recvlen = (int)newlen + off;
1664         else
1665         {
1666             logmsg(_("HHCSH037E uncompress error %d, off %d len %d\n"),
1667                    rc, off, len - off);
1668             recvlen = -1;
1669         }
1670 #else
1671         logmsg(_("HHCSH038E data compressed using libz, unsupported\n"));
1672         recvlen = -1;
1673 #endif
1674     }
1675     else if (comp == SHRD_BZIP2)
1676     {
1677 #ifdef CCKD_BZIP2
1678         unsigned int newlen;
1679 
1680         if (off > 0)
1681             memcpy (buf, cbuf, off);
1682 
1683         newlen = buflen - off;
1684         rc = BZ2_bzBuffToBuffDecompress((void *)(buf + off), &newlen, (void *)(cbuf + off), len - off, 0, 0);
1685         if (rc == BZ_OK)
1686             recvlen = (int)newlen + off;
1687         else
1688         {
1689             logmsg(_("HHCSH039E decompress error %d, off %d len %d\n"),
1690                    rc, off, len - off);
1691             recvlen = -1;
1692         }
1693 #else
1694         logmsg(_("HHCSH040E data compressed using bzip2, unsupported\n"));
1695         recvlen = -1;
1696 #endif
1697     }
1698 
1699     if (recvlen > 0)
1700     {
1701         SHRD_SET_HDR (hdr, cmd, flag, devnum, id, recvlen);
1702         if (comp)
1703             shrdtrc(dev,"recvData    %2.2x %2.2x %2.2x %d %d (uncompressed)\n",
1704                      cmd, flag, devnum, id, recvlen);
1705     }
1706 
1707     return recvlen;
1708 
1709 } /* recvData */
1710 
1711 /*-------------------------------------------------------------------
1712  * Process a request (server side)
1713  *-------------------------------------------------------------------*/
serverRequest(DEVBLK * dev,int ix,BYTE * hdr,BYTE * buf)1714 static void serverRequest (DEVBLK *dev, int ix, BYTE *hdr, BYTE *buf)
1715 {
1716 int      rc;                            /* Return code               */
1717 int      i;                             /* Loop index                */
1718 BYTE     cmd;                           /* Header command            */
1719 BYTE     flag;                          /* Header flags              */
1720 U16      devnum;                        /* Header device number      */
1721 int      id;                            /* Header identifier         */
1722 int      len;                           /* Header length             */
1723 int      code;                          /* Response code             */
1724 int      rcd;                           /* Record to read/write      */
1725 int      off;                           /* Offset into record        */
1726 
1727     /* Extract header information */
1728     SHRD_GET_HDR (hdr, cmd, flag, devnum, id, len);
1729 
1730     shrdtrc(dev,"server_request [%d] %2.2x %2.2x %2.2x %d %d\n",
1731              ix, cmd, flag, devnum, id, len);
1732 
1733     dev->shrd[ix]->time = time (NULL);
1734 
1735     switch (cmd) {
1736 
1737     case SHRD_CONNECT:
1738         if (dev->connecting)
1739         {
1740             serverError (dev, ix, SHRD_ERROR_NOTINIT, cmd,
1741                          "device not initialized");
1742             break;
1743         }
1744         if ((flag >> 4) != SHARED_VERSION)
1745         {
1746             serverError (dev, ix, SHRD_ERROR_BADVERS, cmd,
1747                          "shared version mismatch");
1748             break;
1749         }
1750         dev->shrd[ix]->release = flag & 0x0f;
1751         SHRD_SET_HDR (hdr, 0, (SHARED_VERSION << 4) | SHARED_RELEASE, dev->devnum, id, 2);
1752         store_hw (buf, id);
1753         serverSend (dev, ix, hdr, buf, 2);
1754         break;
1755 
1756     case SHRD_DISCONNECT:
1757         SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 0);
1758         serverSend (dev, ix, hdr, NULL, 0);
1759         dev->shrd[ix]->disconnect = 1;
1760 
1761         obtain_lock (&dev->lock);
1762 
1763         /* Make the device available if this system active on it */
1764         if (dev->ioactive == id)
1765         {
1766             if (!dev->suspended)
1767             {
1768                 dev->busy = 0;
1769                 dev->ioactive = DEV_SYS_NONE;
1770             }
1771             else
1772                 dev->ioactive = DEV_SYS_LOCAL;
1773             if (dev->iowaiters)
1774                 signal_condition (&dev->iocond);
1775         }
1776 
1777         release_lock (&dev->lock);
1778         break;
1779 
1780     case SHRD_START:
1781     case SHRD_RESUME:
1782 
1783         obtain_lock (&dev->lock);
1784 
1785         /* If the device is suspended locally then grab it */
1786         if (dev->ioactive == DEV_SYS_LOCAL && dev->suspended && !dev->reserved)
1787             dev->ioactive = id;
1788 
1789         /* Check if the device is busy */
1790         if (dev->ioactive != id && dev->ioactive != DEV_SYS_NONE)
1791         {
1792             shrdtrc(dev,"server_request busy id=%d ioactive=%d reserved=%d\n",
1793                     id,dev->ioactive,dev->reserved);
1794             /* If the `nowait' bit is on then respond `busy' */
1795             if (flag & SHRD_NOWAIT)
1796             {
1797                 release_lock (&dev->lock);
1798                 SHRD_SET_HDR (hdr, SHRD_BUSY, 0, dev->devnum, id, 0);
1799                 serverSend (dev, ix, hdr, NULL, 0);
1800                 break;
1801             }
1802 
1803             dev->shrd[ix]->waiting = 1;
1804 
1805             /* Wait while the device is busy by the local system */
1806             while (dev->ioactive == DEV_SYS_LOCAL && !dev->suspended)
1807             {
1808                 dev->iowaiters++;
1809                 wait_condition (&dev->iocond, &dev->lock);
1810                 dev->iowaiters--;
1811             }
1812 
1813             /* Return with the `waiting' bit on if busy by a remote system */
1814             if (dev->ioactive != DEV_SYS_NONE && dev->ioactive != DEV_SYS_LOCAL)
1815             {
1816                 release_lock (&dev->lock);
1817                 break;
1818             }
1819 
1820             dev->shrd[ix]->waiting = 0;
1821         }
1822 
1823         /* Make this system active on the device */
1824         dev->ioactive = id;
1825         dev->busy = 1;
1826         dev->syncio_active = dev->syncio_retry = 0;
1827         sysblk.shrdcount++;
1828         shrdtrc(dev,"server_request active id=%d\n", id);
1829 
1830         release_lock(&dev->lock);
1831 
1832         /* Call the i/o start or resume exit */
1833         if (cmd == SHRD_START && dev->hnd->start)
1834             (dev->hnd->start) (dev);
1835         else if (cmd == SHRD_RESUME && dev->hnd->resume)
1836             (dev->hnd->resume) (dev);
1837 
1838         /* Get the purge list */
1839         if (dev->shrd[ix]->purgen == 0)
1840             code = len = 0;
1841         else
1842         {
1843             code = SHRD_PURGE;
1844             if (dev->shrd[ix]->purgen < 0)
1845                 len = 0;
1846             else
1847                 len = 4 * dev->shrd[ix]->purgen;
1848         }
1849 
1850         /* Send the response */
1851         SHRD_SET_HDR (hdr, code, 0, dev->devnum, id, len);
1852         rc = serverSend (dev, ix, hdr, (BYTE *)dev->shrd[ix]->purge, len);
1853         if (rc >= 0)
1854             dev->shrd[ix]->purgen = 0;
1855         break;
1856 
1857     case SHRD_END:
1858     case SHRD_SUSPEND:
1859         /* Must be active on the device for this command */
1860         if (dev->ioactive != id)
1861         {
1862             serverError (dev, ix, SHRD_ERROR_NOTACTIVE, cmd,
1863                          "not active on this device");
1864             break;
1865         }
1866 
1867         /* Call the I/O end/suspend exit */
1868         if (cmd == SHRD_END && dev->hnd->end)
1869             (dev->hnd->end) (dev);
1870         else if (cmd == SHRD_SUSPEND && dev->hnd->suspend)
1871             (dev->hnd->suspend) (dev);
1872 
1873         obtain_lock (&dev->lock);
1874 
1875         /* Make the device available if it's not reserved */
1876         if (!dev->reserved)
1877         {
1878             /* If locally suspended then return the device to local */
1879             if (dev->suspended)
1880             {
1881                 dev->ioactive = DEV_SYS_LOCAL;
1882                 dev->busy = 1;
1883             }
1884             else
1885             {
1886                 dev->ioactive = DEV_SYS_NONE;
1887                 dev->busy = 0;
1888             }
1889 
1890             /* Reset any `waiting' bits */
1891             for (i = 0; i < SHARED_MAX_SYS; i++)
1892                 if (dev->shrd[i])
1893                     dev->shrd[i]->waiting = 0;
1894 
1895             /* Notify any waiters */
1896             if (dev->iowaiters)
1897                 signal_condition (&dev->iocond);
1898         }
1899         shrdtrc(dev,"server_request inactive id=%d\n", id);
1900 
1901         release_lock (&dev->lock);
1902 
1903         /* Send response back */
1904         SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 0);
1905         serverSend (dev, ix, hdr, NULL, 0);
1906         break;
1907 
1908     case SHRD_RESERVE:
1909         /* Must be active on the device for this command */
1910         if (dev->ioactive != id)
1911         {
1912             serverError (dev, ix, SHRD_ERROR_NOTACTIVE, cmd,
1913                          "not active on this device");
1914             break;
1915         }
1916 
1917         obtain_lock (&dev->lock);
1918         dev->reserved = 1;
1919         release_lock (&dev->lock);
1920 
1921         shrdtrc(dev,"server_request reserved id=%d\n", id);
1922 
1923         /* Call the I/O reserve exit */
1924         if (dev->hnd->reserve) (dev->hnd->reserve) (dev);
1925 
1926         /* Send response back */
1927         SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 0);
1928         serverSend (dev, ix, hdr, NULL, 0);
1929 
1930         break;
1931 
1932     case SHRD_RELEASE:
1933         /* Must be active on the device for this command */
1934         if (dev->ioactive != id)
1935         {
1936             serverError (dev, ix, SHRD_ERROR_NOTACTIVE, cmd,
1937                          "not active on this device");
1938             break;
1939         }
1940 
1941         /* Call the I/O release exit */
1942         if (dev->hnd->release) (dev->hnd->release) (dev);
1943 
1944         obtain_lock (&dev->lock);
1945         dev->reserved = 0;
1946         release_lock (&dev->lock);
1947 
1948         shrdtrc(dev,"server_request released id=%d\n", id);
1949 
1950         /* Send response back */
1951         SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 0);
1952         serverSend (dev, ix, hdr, NULL, 0);
1953 
1954         break;
1955 
1956     case SHRD_READ:
1957         /* Must be active on the device for this command */
1958         if (dev->ioactive != id)
1959         {
1960             serverError (dev, ix, SHRD_ERROR_NOTACTIVE, cmd,
1961                          "not active on this device");
1962             break;
1963         }
1964 
1965         /* Set the compressions client is willing to accept */
1966         dev->comps = dev->shrd[ix]->comps;
1967         dev->comp = dev->compoff = 0;
1968 
1969         /* Call the I/O read exit */
1970         rcd = (int)fetch_fw (buf);
1971         rc = (dev->hnd->read) (dev, rcd, &flag);
1972         shrdtrc(dev,"server_request read rcd %d flag %2.2x rc=%d\n",
1973                 rcd, flag, rc);
1974 
1975         if (rc < 0)
1976             code = SHRD_IOERR;
1977         else
1978         {
1979             code = dev->comp ? SHRD_COMP : 0;
1980             flag = (dev->comp << 4) | dev->compoff;
1981         }
1982 
1983         /* Reset compression stuff */
1984         dev->comps = dev->comp = dev->compoff = 0;
1985 
1986         SHRD_SET_HDR (hdr, code, flag, dev->devnum, id, dev->buflen);
1987         serverSend (dev, ix, hdr, dev->buf, dev->buflen);
1988 
1989         break;
1990 
1991     case SHRD_WRITE:
1992         /* Must be active on the device for this command */
1993         if (dev->ioactive != id)
1994         {
1995             serverError (dev, ix, SHRD_ERROR_NOTACTIVE, cmd,
1996                          "not active on this device");
1997             break;
1998         }
1999 
2000         /* Call the I/O write exit */
2001         off = fetch_hw (buf);
2002         rcd = fetch_fw (buf + 2);
2003 
2004         rc = (dev->hnd->write) (dev, rcd, off, buf + 6, len - 6, &flag);
2005         shrdtrc(dev,"server_request write rcd %d off %d len %d flag %2.2x rc=%d\n",
2006                 rcd, off, len - 6, flag, rc);
2007 
2008         if (rc < 0)
2009             code = SHRD_IOERR;
2010         else
2011             code = 0;
2012 
2013         /* Send response back */
2014         SHRD_SET_HDR (hdr, code, flag, dev->devnum, id, 0);
2015         serverSend (dev, ix, hdr, NULL, 0);
2016 
2017         break;
2018 
2019     case SHRD_SENSE:
2020         /* Must be active on the device for this command */
2021         if (dev->ioactive != id)
2022         {
2023             serverError (dev, ix, SHRD_ERROR_NOTACTIVE, cmd,
2024                          "not active on this device");
2025             break;
2026         }
2027 
2028         /* Send the sense */
2029         SHRD_SET_HDR (hdr, 0, CSW_CE | CSW_DE, dev->devnum, id, dev->numsense);
2030         serverSend (dev, ix, hdr, dev->sense, dev->numsense);
2031         memset (dev->sense, 0, sizeof(dev->sense));
2032         dev->sns_pending = 0;
2033         break;
2034 
2035     case SHRD_QUERY:
2036         switch (flag) {
2037 
2038         case SHRD_USED:
2039             if (dev->hnd->used)
2040                 rc = (dev->hnd->used) (dev);
2041             else
2042                 rc = 0;
2043             store_fw (buf, rc);
2044             SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 4);
2045             serverSend (dev, ix, hdr, buf, 4);
2046             break;
2047 
2048         case SHRD_DEVCHAR:
2049             SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, dev->numdevchar);
2050             serverSend (dev, ix, hdr, dev->devchar, dev->numdevchar);
2051             break;
2052 
2053         case SHRD_DEVID:
2054             SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, dev->numdevid);
2055             serverSend (dev, ix, hdr, dev->devid, dev->numdevid);
2056             break;
2057 
2058         case SHRD_CKDCYLS:
2059             store_fw (buf, dev->ckdcyls);
2060             SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 4);
2061             serverSend (dev, ix, hdr, buf, 4);
2062             break;
2063 
2064         case SHRD_FBAORIGIN:
2065             store_fw (buf, dev->fbaorigin);
2066             SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 4);
2067             serverSend (dev, ix, hdr, buf, 4);
2068             break;
2069 
2070         case SHRD_FBANUMBLK:
2071             store_fw (buf, dev->fbanumblk);
2072             SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 4);
2073             serverSend (dev, ix, hdr, buf, 4);
2074             break;
2075 
2076         case SHRD_FBABLKSIZ:
2077             store_fw (buf, dev->fbablksiz);
2078             SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 4);
2079             serverSend (dev, ix, hdr, buf, 4);
2080             break;
2081 
2082         default:
2083             serverError (dev, ix, SHRD_ERROR_INVALID, cmd,
2084                          "invalid query request");
2085             break;
2086         } /* switch (flag) for SHRD_QUERY */
2087         break;
2088 
2089     case SHRD_COMPRESS:
2090 #ifdef HAVE_LIBZ
2091         dev->shrd[ix]->comp = (flag & 0x0f);
2092         store_hw (buf, dev->shrd[ix]->comp);
2093 #else
2094         store_hw (buf, 0);
2095 #endif
2096         dev->shrd[ix]->comps = (flag & 0xf0) >> 4;
2097         SHRD_SET_HDR (hdr, 0, 0, dev->devnum, id, 2);
2098         serverSend (dev, ix, hdr, buf, 2);
2099         break;
2100 
2101     default:
2102         serverError (dev, ix, SHRD_ERROR_INVALID, cmd,
2103                      "invalid request");
2104         break;
2105     } /* switch (cmd) */
2106 } /* serverRequest */
2107 
2108 /*-------------------------------------------------------------------
2109  * Locate the SHRD block for a socket (server side)
2110  *-------------------------------------------------------------------*/
serverLocate(DEVBLK * dev,int id,int * avail)2111 static int serverLocate (DEVBLK *dev, int id, int *avail)
2112 {
2113 int      i;                             /* Loop index                */
2114 
2115     if (avail) *avail = -1;
2116     for (i = 0; i < SHARED_MAX_SYS; i++)
2117     {
2118         if (dev->shrd[i])
2119         {
2120             if (dev->shrd[i]->id == id)
2121                 return i;
2122         }
2123         else if (avail && *avail < 0)
2124             *avail = i;
2125     }
2126     return -1;
2127 } /* serverLocate */
2128 
2129 /*-------------------------------------------------------------------
2130  * Return a new Identifier (server side)
2131  *-------------------------------------------------------------------*/
serverId(DEVBLK * dev)2132 static int serverId (DEVBLK *dev)
2133 {
2134 int      i;                             /* Loop index                */
2135 int      id;                            /* Identifier                */
2136 
2137     do {
2138         ++dev->shrdid;
2139         dev->shrdid &= 0xffff;
2140         if (dev->shrdid == DEV_SYS_LOCAL
2141          || dev->shrdid == DEV_SYS_NONE)
2142             dev->shrdid = 1;
2143         id = dev->shrdid;
2144 
2145         for (i = 0; i < SHARED_MAX_SYS; i++)
2146             if (dev->shrd[i] && dev->shrd[i]->id == id)
2147                 break;
2148 
2149     } while (i < SHARED_MAX_SYS);
2150 
2151     return id;
2152 } /* serverId */
2153 
2154 /*-------------------------------------------------------------------
2155  * Respond with an error message (server side)
2156  *-------------------------------------------------------------------*/
serverError(DEVBLK * dev,int ix,int code,int status,char * msg)2157 static int serverError (DEVBLK *dev, int ix, int code, int status,
2158                         char *msg)
2159 {
2160 int rc;                                 /* Return code               */
2161 size_t len;                             /* Message length            */
2162 BYTE hdr[SHRD_HDR_SIZE];                /* Header                    */
2163 
2164     /* Get message length */
2165     len = strlen(msg) + 1;
2166     if (len > SHARED_MAX_MSGLEN)
2167         len = SHARED_MAX_MSGLEN;
2168 
2169     SHRD_SET_HDR (hdr, code, status, dev ? dev->devnum : 0,
2170                   ix < 0 ? 0 : dev->shrd[ix]->id, (U16)len);
2171 
2172     shrdtrc(dev,"server_error %2.2x %2.2x: %s\n", code, status, msg);
2173 
2174     rc = serverSend (dev, ix, hdr, (BYTE *)msg, (int)len);
2175     return rc;
2176 
2177 } /* serverError */
2178 
2179 /*-------------------------------------------------------------------
2180  * Send data (server side)
2181  *-------------------------------------------------------------------*/
serverSend(DEVBLK * dev,int ix,BYTE * hdr,BYTE * buf,int buflen)2182 static int serverSend (DEVBLK *dev, int ix, BYTE *hdr, BYTE *buf,
2183                        int buflen)
2184 {
2185 int      rc;                            /* Return code               */
2186 int      sock;                          /* Socket number             */
2187 BYTE     code;                          /* Header code               */
2188 BYTE     status;                        /* Header status             */
2189 U16      devnum;                        /* Header device number      */
2190 int      id;                            /* Header identifier         */
2191 int      len;                           /* Header length             */
2192 int      hdrlen;                        /* Header length + other data*/
2193 BYTE    *sendbuf = NULL;                /* Send buffer               */
2194 int      sendlen;                       /* Send length               */
2195 BYTE     cbuf[SHRD_HDR_SIZE + 65536];   /* Combined buffer           */
2196 
2197     /* Make buf, buflen consistent if no additional data to be sent  */
2198     if (buf == NULL) buflen = 0;
2199     else if (buflen == 0) buf = NULL;
2200 
2201     /* Calculate length of header, may contain additional data */
2202     SHRD_GET_HDR(hdr, code, status, devnum, id, len);
2203     hdrlen = SHRD_HDR_SIZE + (len - buflen);
2204     sendlen = hdrlen + buflen;
2205 
2206     /* Check if buf is adjacent to the header */
2207     if (buf && hdr + hdrlen == buf)
2208     {
2209         hdrlen += buflen;
2210         buf = NULL;
2211         buflen = 0;
2212     }
2213 
2214     /* Send only the header buffer if `buf' is empty */
2215     if (buflen == 0)  sendbuf = hdr;
2216 
2217     /* Get socket number; if `ix' < 0 we don't have a device yet */
2218     if (ix >= 0)
2219         sock = dev->shrd[ix]->fd;
2220     else
2221     {
2222         sock = -ix;
2223         dev = NULL;
2224     }
2225 
2226     shrdtrc(dev,"server_send %2.2x %2.2x %2.2x %d %d\n",
2227             code, status, devnum, id, len);
2228 
2229 #ifdef HAVE_LIBZ
2230     /* Compress the buf */
2231     if (ix >= 0 && dev->shrd[ix]->comp != 0
2232      && code == SHRD_OK && status == 0
2233      && hdrlen - SHRD_HDR_SIZE <= SHRD_COMP_MAX_OFF
2234      && buflen >= SHARED_COMPRESS_MINLEN)
2235     {
2236         unsigned long newlen;
2237         int off = hdrlen - SHRD_HDR_SIZE;
2238         sendbuf = cbuf;
2239         newlen = sizeof(cbuf) - hdrlen;
2240         memcpy (cbuf, hdr, hdrlen);
2241         rc = compress2 (cbuf + hdrlen, &newlen,
2242                         buf, buflen, dev->shrd[ix]->comp);
2243         if (rc == Z_OK && (int)newlen < buflen)
2244         {
2245             /* Setup to use the compressed buffer */
2246             sendlen = hdrlen + newlen;
2247             buflen = 0;
2248             code = SHRD_COMP;
2249             status = (SHRD_LIBZ << 4) | off;
2250             SHRD_SET_HDR (cbuf, code, status, devnum, id, newlen + off);
2251             shrdtrc(dev,"server_send %2.2x %2.2x %2.2x %d %d (compressed)\n",
2252                    code,status,devnum,id,(int)newlen+off);
2253         }
2254     }
2255 #endif
2256 
2257     /* Build combined (hdr + data) buffer */
2258     if (buflen > 0)
2259     {
2260         sendbuf = cbuf;
2261         memcpy (cbuf, hdr, hdrlen);
2262         memcpy (cbuf + hdrlen, buf, buflen);
2263     }
2264 
2265     /* Send the combined header and data */
2266     rc = send (sock, sendbuf, sendlen, 0);
2267 
2268     /* Process return code */
2269     if (rc < 0)
2270     {
2271         logmsg(_("HHCSH041E %4.4X send error %d id=%d: %s\n"),
2272                dev->devnum, HSO_errno, id, strerror(HSO_errno));
2273         dev->shrd[ix]->disconnect = 1;
2274     }
2275 
2276     return rc;
2277 
2278 } /* serverSend */
2279 
2280 /*-------------------------------------------------------------------
2281  * Determine if a client can be disconnected (server side)
2282  *-------------------------------------------------------------------*/
serverDisconnectable(DEVBLK * dev,int ix)2283 static int serverDisconnectable (DEVBLK *dev, int ix) {
2284 
2285     if (dev->shrd[ix]->waiting || dev->shrd[ix]->pending
2286      || dev->ioactive == dev->shrd[ix]->id)
2287         return 0;
2288     else
2289         return 1;
2290 } /* serverDisconnectable */
2291 
2292 /*-------------------------------------------------------------------
2293  * Disconnect a client (server side)
2294  * dev->lock *must* be held
2295  *-------------------------------------------------------------------*/
serverDisconnect(DEVBLK * dev,int ix)2296 static void serverDisconnect (DEVBLK *dev, int ix) {
2297 int id;                                 /* Client identifier         */
2298 int i;                                  /* Loop index                */
2299 
2300     id = dev->shrd[ix]->id;
2301 
2302 //FIXME: Handle a disconnected busy client better
2303 //       Perhaps a disconnect timeout value... this will
2304 //       give the client time to reconnect.
2305 
2306     /* If the device is active by the client then extricate it.
2307        This is *not* a good situation */
2308     if (dev->ioactive == id)
2309     {
2310         logmsg(_("HHCSH042W %4.4X busy client being removed id=%d %s\n"),
2311                dev->devnum, id, dev->reserved ? "reserved" : "");
2312 
2313         /* Call the I/O release exit if reserved by this client */
2314         if (dev->reserved && dev->hnd->release)
2315             (dev->hnd->release) (dev);
2316 
2317         /* Call the channel program end exit */
2318         if (dev->hnd->end)
2319             (dev->hnd->end) (dev);
2320 
2321         /* Reset any `waiting' bits */
2322         for (i = 0; i < SHARED_MAX_SYS; i++)
2323             if (dev->shrd[i])
2324                 dev->shrd[i]->waiting = 0;
2325 
2326         /* Make the device available */
2327         if (dev->suspended) {
2328             dev->ioactive = DEV_SYS_LOCAL;
2329             dev->busy = 1;
2330         }
2331         else
2332         {
2333             dev->ioactive = DEV_SYS_NONE;
2334             dev->busy = 0;
2335         }
2336 
2337         /* Notify any waiters */
2338         if (dev->iowaiters)
2339             signal_condition (&dev->iocond);
2340     }
2341 
2342     logmsg(_("HHCSH043I %s disconnected from %4.4X id=%d\n"),
2343         dev->shrd[ix]->ipaddr, dev->devnum, id);
2344 
2345     /* Release the SHRD block */
2346     close_socket (dev->shrd[ix]->fd);
2347     free (dev->shrd[ix]->ipaddr);
2348     free (dev->shrd[ix]);
2349     dev->shrd[ix] = NULL;
2350 
2351     dev->shrdconn--;
2352 } /* serverDisconnect */
2353 
2354 /*-------------------------------------------------------------------
2355  * Return client ip
2356  *-------------------------------------------------------------------*/
clientip(int sock)2357 static char *clientip (int sock)
2358 {
2359 int                     rc;             /* Return code               */
2360 struct sockaddr_in      client;         /* Client address structure  */
2361 socklen_t               namelen;        /* Length of client structure*/
2362 
2363     namelen = sizeof(client);
2364     rc = getpeername (sock, (struct sockaddr *)&client, &namelen);
2365     return inet_ntoa(client.sin_addr);
2366 
2367 } /* clientip */
2368 
2369 /*-------------------------------------------------------------------
2370  * Find device by device number
2371  *-------------------------------------------------------------------*/
findDevice(U16 devnum)2372 static DEVBLK *findDevice (U16 devnum)
2373 {
2374 DEVBLK      *dev;                       /* -> Device block           */
2375 
2376     for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev)
2377         if (dev->devnum == devnum) break;
2378     return dev;
2379 
2380 } /* findDevice */
2381 
2382 /*-------------------------------------------------------------------
2383  * Connect a new client
2384  *-------------------------------------------------------------------*/
serverConnect(int * psock)2385 static void *serverConnect (int *psock)
2386 {
2387 int             csock;                  /* Connection socket         */
2388 int             rc;                     /* Return code               */
2389 BYTE            cmd;                    /* Request command           */
2390 BYTE            flag;                   /* Request flag              */
2391 U16             devnum;                 /* Request device number     */
2392 int             id;                     /* Request id                */
2393 int             len;                    /* Request data length       */
2394 int             ix;                     /* Client index              */
2395 DEVBLK         *dev=NULL;               /* -> Device block           */
2396 time_t          now;                    /* Current time              */
2397 fd_set          selset;                 /* Read bit map for select   */
2398 int             maxfd;                  /* Max fd for select         */
2399 struct timeval  wait;                   /* Wait time for select      */
2400 BYTE            hdr[SHRD_HDR_SIZE + 65536];  /* Header + buffer      */
2401 BYTE           *buf = hdr + SHRD_HDR_SIZE;   /* Buffer               */
2402 char           *ipaddr = NULL;          /* IP addr of connected peer */
2403 
2404     csock = *psock;
2405     free (psock);
2406     ipaddr = clientip(csock);
2407 
2408     shrdtrc(dev,"server_connect %s sock %d\n",ipaddr,csock);
2409 
2410     rc = recvData(csock, hdr, buf, 65536, 1);
2411     if (rc < 0)
2412     {
2413         logmsg(_("HHCSH0474 %s connect failed\n"), ipaddr);
2414         close_socket (csock);
2415         return NULL;
2416     }
2417     SHRD_GET_HDR (hdr, cmd, flag, devnum, id, len);
2418 
2419     /* Error if not a connect request */
2420     if (id == 0 && cmd != SHRD_CONNECT)
2421     {
2422         serverError (NULL, -csock, SHRD_ERROR_NOTCONN, cmd,
2423                      "not a connect request");
2424         close_socket (csock);
2425         return NULL;
2426     }
2427 
2428     /* Locate the device */
2429     dev = findDevice (devnum);
2430 
2431     /* Error if device not found */
2432     if (dev == NULL)
2433     {
2434         serverError (NULL, -csock, SHRD_ERROR_NODEVICE, cmd,
2435                      "device not found");
2436         close_socket (csock);
2437         return NULL;
2438     }
2439 
2440     /* Obtain the device lock */
2441     obtain_lock (&dev->lock);
2442 
2443     /* Find an available slot for the connection */
2444     rc = serverLocate (dev, id, &ix);
2445 
2446     /* Error if already connected */
2447     if (rc >= 0)
2448     {
2449         release_lock (&dev->lock);
2450         serverError (NULL, -csock, SHRD_ERROR_NODEVICE, cmd,
2451                      "already connected");
2452         close_socket (csock);
2453         return NULL;
2454     }
2455 
2456     /* Error if no available slot */
2457     if (ix < 0)
2458     {
2459         release_lock (&dev->lock);
2460         serverError (NULL, -csock, SHRD_ERROR_NOTAVAIL, cmd,
2461                      "too many connections");
2462         close_socket (csock);
2463         return NULL;
2464     }
2465 
2466     /* Obtain SHRD block */
2467     dev->shrd[ix] = calloc (sizeof(SHRD), 1);
2468 
2469     /* Error if not obtained */
2470     if (dev->shrd[ix] == NULL)
2471     {
2472         release_lock (&dev->lock);
2473         serverError (NULL, -csock, SHRD_ERROR_NOMEM, cmd,
2474                      "calloc() failure");
2475         close_socket (csock);
2476         return NULL;
2477     }
2478 
2479     /* Initialize the SHRD block */
2480     dev->shrd[ix]->pending = 1;
2481     dev->shrd[ix]->havehdr = 1;
2482     if (id == 0) id = serverId (dev);
2483     dev->shrd[ix]->id = id;
2484     dev->shrd[ix]->fd = csock;
2485     dev->shrd[ix]->ipaddr = strdup(ipaddr);
2486     dev->shrd[ix]->time = time (NULL);
2487     dev->shrd[ix]->purgen = -1;
2488     dev->shrdconn++;
2489     SHRD_SET_HDR (dev->shrd[ix]->hdr, cmd, flag, devnum, id, len);
2490 
2491     logmsg (_("HHCSH053I %s connected to %4.4X id=%d\n"),
2492             ipaddr, devnum, id);
2493 
2494     /* Return if device thread already active */
2495     if (dev->shrdtid)
2496     {
2497         if (dev->shrdwait)
2498         {
2499             signal_thread (dev->shrdtid, SIGUSR2);
2500         }
2501         release_lock (&dev->lock);
2502         return NULL;
2503     }
2504     dev->shrdtid = thread_id();
2505 
2506     /* This thread will be the shared device thread */
2507     logmsg (_("HHCSH045I Shared device %4.4X thread started: "
2508             "tid="TIDPAT", pid=%d\n"),
2509             dev->devnum, thread_id(), getpid());
2510 
2511     while (dev->shrdconn)
2512     {
2513         FD_ZERO (&selset);
2514         maxfd = -1;
2515 
2516         /* Get the current time */
2517         now = time (NULL);
2518 
2519         for (ix = 0; ix < SHARED_MAX_SYS; ix++)
2520         {
2521             if (dev->shrd[ix])
2522             {
2523                 /* Exit loop if pending and not waiting */
2524                 if (dev->shrd[ix]->pending && !dev->shrd[ix]->waiting)
2525                     break;
2526 
2527                 /* Disconnect if not a valid socket */
2528                 if ( !socket_is_socket( dev->shrd[ix]->fd ) )
2529                     dev->shrd[ix]->disconnect = 1;
2530 
2531                 /* See if the connection can be timed out */
2532                 else if (now - dev->shrd[ix]->time > SHARED_TIMEOUT
2533                  && serverDisconnectable (dev, ix))
2534                     dev->shrd[ix]->disconnect = 1;
2535 
2536                 /* Disconnect if the disconnect bit is set */
2537                 if (dev->shrd[ix]->disconnect)
2538                     serverDisconnect (dev, ix);
2539 
2540                 /* Otherwise set the fd if not waiting */
2541                 else if (!dev->shrd[ix]->waiting)
2542                 {
2543                     FD_SET (dev->shrd[ix]->fd, &selset);
2544                     if (dev->shrd[ix]->fd >= maxfd)
2545                         maxfd = dev->shrd[ix]->fd + 1;
2546                     shrdtrc(dev,"select   set %d id=%d\n",dev->shrd[ix]->fd,dev->shrd[ix]->id);
2547                 }
2548             }
2549 
2550         }
2551 
2552         /* Wait for a request if no pending requests */
2553         if (ix >= SHARED_MAX_SYS)
2554         {
2555             /* Exit thread if nothing to select */
2556             if (maxfd < 0) continue;
2557 
2558             /* Wait for a file descriptor to become busy */
2559             wait.tv_sec = 10; /*SHARED_SELECT_WAIT;*/
2560             wait.tv_usec = 0;
2561             release_lock (&dev->lock);
2562 
2563             dev->shrdwait = 1;
2564             rc = select ( maxfd, &selset, NULL, NULL, &wait );
2565             dev->shrdwait = 0;
2566 
2567             obtain_lock (&dev->lock);
2568 
2569             shrdtrc(dev,"select rc %d\n",rc);
2570 
2571             if (rc == 0) continue;
2572 
2573             if (rc < 0 )
2574             {
2575                 if (HSO_errno == HSO_EINTR || HSO_errno == HSO_EBADF) continue;
2576                 logmsg(_("HHCSH046E select: %s\n"), strerror(HSO_errno));
2577                 break;
2578             }
2579 
2580             /* Find any pending requests */
2581             for (ix = 0; ix < SHARED_MAX_SYS; ix++)
2582             {
2583                 if (dev->shrd[ix]
2584                  && FD_ISSET(dev->shrd[ix]->fd, &selset))
2585                 {
2586                     dev->shrd[ix]->pending = 1;
2587                     shrdtrc(dev,"select isset %d id=%d\n",dev->shrd[ix]->fd,dev->shrd[ix]->id);
2588                 }
2589             }
2590             continue;
2591         }
2592 
2593         /* Found a pending request */
2594         release_lock (&dev->lock);
2595 
2596         shrdtrc(dev,"select ready %d id=%d\n",dev->shrd[ix]->fd,dev->shrd[ix]->id);
2597 
2598         if (dev->shrd[ix]->havehdr)
2599         {
2600             /* Copy the saved start/resume packet */
2601             memcpy (hdr, dev->shrd[ix]->hdr, SHRD_HDR_SIZE);
2602             dev->shrd[ix]->havehdr = dev->shrd[ix]->waiting = 0;
2603         }
2604         else
2605         {
2606             /* Read the request packet */
2607             rc = recvData (dev->shrd[ix]->fd, hdr, buf, 65536, 1);
2608             if (rc < 0)
2609             {
2610                 logmsg(_("HHCSH047E %4.4X %s recv error id=%d\n"),
2611                     dev->devnum, dev->shrd[ix]->ipaddr, dev->shrd[ix]->id);
2612                 dev->shrd[ix]->disconnect = 1;
2613                 dev->shrd[ix]->pending = 0;
2614                 obtain_lock (&dev->lock);
2615                 continue;
2616             }
2617         }
2618 
2619         /* Process the request */
2620         serverRequest (dev, ix, hdr, buf);
2621 
2622         obtain_lock (&dev->lock);
2623 
2624         /* If the `waiting' bit is on then the start/resume request
2625            failed because the device is busy on some other remote
2626            system.  We only need to save the header because the data
2627            is ignored for start/resume.
2628         */
2629         if (dev->shrd[ix]->waiting)
2630         {
2631             memcpy (dev->shrd[ix]->hdr, hdr, SHRD_HDR_SIZE);
2632             dev->shrd[ix]->havehdr = 1;
2633         }
2634         else
2635             dev->shrd[ix]->pending = 0;
2636     }
2637 
2638     dev->shrdtid = 0;
2639     release_lock (&dev->lock);
2640 
2641     logmsg (_("HHCSH048I Shared device %4.4X thread stopping\n"),
2642             dev->devnum);
2643 
2644     return NULL;
2645 
2646 } /* serverConnect */
2647 
2648 /*-------------------------------------------------------------------
2649  * General trace routine for shared devices
2650  *-------------------------------------------------------------------*/
shrdtrc(DEVBLK * dev,char * msg,...)2651 static void shrdtrc (DEVBLK *dev, char *msg, ...)
2652 {
2653 int             dt;
2654 struct timeval  tv;
2655 SHRD_TRACE      s;
2656 va_list         vl;
2657 
2658     dt = (dev != NULL && (dev->ccwtrace||dev->ccwstep));
2659     if (dt == 0 && sysblk.shrdtrace == 0) return;
2660 
2661     va_start(vl,msg);
2662     gettimeofday(&tv, NULL);
2663     sprintf ((char *)s,
2664             "%6.6ld" "." "%6.6ld %4.4X:",
2665             tv.tv_sec, (long)(tv.tv_usec), dev ? dev->devnum : 0);
2666     vsnprintf ((char *)s + strlen(s), sizeof(s) - strlen(s),
2667             msg, vl);
2668     if (dt)
2669     {
2670         logmsg (s+14);
2671     }
2672     if (sysblk.shrdtrace)
2673     {
2674         SHRD_TRACE *p = sysblk.shrdtracep++;
2675         if (p >= sysblk.shrdtracex)
2676         {
2677             p = sysblk.shrdtrace;
2678             sysblk.shrdtracep = p + 1;
2679         }
2680         if (p) memcpy(p, s, sizeof(*p));
2681     }
2682 
2683 } /* shrdtrc */
2684 
2685 /*-------------------------------------------------------------------
2686  * Shared device server
2687  *-------------------------------------------------------------------*/
shared_server(void * arg)2688 DLL_EXPORT void *shared_server (void *arg)
2689 {
2690 int                     rc;             /* Return code               */
2691 int                     hi;             /* Hi fd for select          */
2692 int                     lsock;          /* inet socket for listening */
2693 int                     usock;          /* unix socket for listening */
2694 int                     rsock;          /* Ready socket              */
2695 int                     csock;          /* Socket for conversation   */
2696 int                    *psock;          /* Pointer to socket         */
2697 struct sockaddr_in      server;         /* Server address structure  */
2698 #if defined( HAVE_SYS_UN_H )
2699 struct sockaddr_un      userver;        /* Unix address structure    */
2700 #endif
2701 int                     optval;         /* Argument for setsockopt   */
2702 fd_set                  selset;         /* Read bit map for select   */
2703 TID                     tid;            /* Negotiation thread id     */
2704 
2705     UNREFERENCED(arg);
2706 
2707     /* Display thread started message on control panel */
2708     logmsg (_("HHCSH049I Shared device %d" "." "%d thread started: "
2709             "tid="TIDPAT", pid=%d\n"),
2710             SHARED_VERSION, SHARED_RELEASE, thread_id(), getpid());
2711 
2712     /* Obtain a internet socket */
2713     lsock = socket (AF_INET, SOCK_STREAM, 0);
2714 
2715     if (lsock < 0)
2716     {
2717         logmsg(_("HHCSH050E inet socket: %s\n"), strerror(HSO_errno));
2718         return NULL;
2719     }
2720 
2721     /* Obtain a unix socket */
2722 #if defined( HAVE_SYS_UN_H )
2723     usock = socket (AF_UNIX, SOCK_STREAM, 0);
2724     if (usock < 0)
2725     {
2726         logmsg(_("HHCSH051W unix socket: %s\n"), strerror(HSO_errno));
2727     }
2728 #else
2729     usock = -1;
2730 #endif
2731 
2732     /* Allow previous instance of socket to be reused */
2733     optval = 1;
2734     setsockopt (lsock, SOL_SOCKET, SO_REUSEADDR,
2735                 (GETSET_SOCKOPT_T*)&optval, sizeof(optval));
2736 
2737     /* Prepare the sockaddr structure for the bind */
2738     memset (&server, 0, sizeof(server));
2739     server.sin_family = AF_INET;
2740     server.sin_addr.s_addr = INADDR_ANY;
2741     server.sin_port = sysblk.shrdport;
2742     server.sin_port = htons(server.sin_port);
2743 
2744     /* Attempt to bind the internet socket to the port */
2745     while (1)
2746     {
2747         rc = bind (lsock, (struct sockaddr *)&server, sizeof(server));
2748         if (rc == 0 || HSO_errno != HSO_EADDRINUSE) break;
2749         logmsg (_("HHCSH052W Waiting for port %u to become free\n"),
2750                 sysblk.shrdport);
2751         SLEEP(10);
2752     } /* end while */
2753 
2754     if (rc != 0)
2755     {
2756         logmsg(_("HHCSH053E inet bind: %s\n"), strerror(HSO_errno));
2757         close_socket(lsock); close_socket(usock);
2758         return NULL;
2759     }
2760 
2761 #if defined( HAVE_SYS_UN_H )
2762     /* Bind the unix socket */
2763     if (usock >= 0)
2764     {
2765         userver.sun_family = AF_UNIX;
2766         sprintf(userver.sun_path, "/tmp/hercules_shared.%d", sysblk.shrdport);
2767         unlink(userver.sun_path);
2768         fchmod (usock, 0700);
2769 
2770         rc = bind (usock, (struct sockaddr *)&userver, sizeof(userver));
2771 
2772         if (rc < 0)
2773         {
2774             logmsg(_("HHCSH054W unix bind: %s\n"), strerror(errno));
2775             close(usock);
2776             usock = -1;
2777         }
2778     }
2779 #endif // defined( HAVE_SYS_UN_H )
2780 
2781     /* Put the sockets into listening state */
2782     rc = listen (lsock, SHARED_MAX_SYS);
2783 
2784     if (rc < 0)
2785     {
2786         logmsg(_("HHCSH055E inet listen: %s\n"), strerror(HSO_errno));
2787         close_socket(lsock); close_socket(usock);
2788         return NULL;
2789     }
2790 
2791     if (usock >= 0)
2792     {
2793         rc = listen (usock, SHARED_MAX_SYS);
2794 
2795         if (rc < 0)
2796         {
2797             logmsg(_("HHCSH056W unix listen: %s\n"), strerror(HSO_errno));
2798             close_socket(usock);
2799             usock = -1;
2800         }
2801     }
2802 
2803     sysblk.shrdtid = thread_id();
2804     csock = -1;
2805     if (lsock < usock)
2806         hi = usock + 1;
2807     else
2808         hi = lsock + 1;
2809 
2810     logmsg(_("HHCSH057I Waiting for shared device requests on port %u\n"),
2811             sysblk.shrdport);
2812 
2813     /* Handle connection requests and attention interrupts */
2814     while (!sysblk.shutdown)
2815     {
2816         /* Initialize the select parameters */
2817         FD_ZERO (&selset);
2818         FD_SET (lsock, &selset);
2819         if (usock >= 0)
2820             FD_SET (usock, &selset);
2821 
2822         /* Wait for a file descriptor to become ready */
2823         rc = select ( hi, &selset, NULL, NULL, NULL );
2824 
2825         if (rc == 0) continue;
2826 
2827         if (rc < 0 )
2828         {
2829             if (HSO_errno == HSO_EINTR) continue;
2830             logmsg(_("HHCSH058E select: %s\n"), strerror(HSO_errno));
2831             break;
2832         }
2833 
2834         /* If a client connection request has arrived then accept it */
2835         if (FD_ISSET(lsock, &selset))
2836             rsock = lsock;
2837         else if (usock >= 0 && FD_ISSET(usock, &selset))
2838             rsock = usock;
2839         else
2840             rsock = -1;
2841 
2842         if (rsock > 0)
2843         {
2844             /* Accept a connection and create conversation socket */
2845             csock = accept (rsock, NULL, NULL);
2846             if (csock < 0)
2847             {
2848                 logmsg(_("HHCSH059E accept: %s\n"), strerror(HSO_errno));
2849                 continue;
2850             }
2851 
2852             psock = malloc (sizeof (csock));
2853             if (psock == NULL)
2854             {
2855                 logmsg(_("HHCSH060E malloc size %d: %s\n"),
2856                        sizeof(csock), strerror(HSO_errno));
2857                 close_socket (csock);
2858                 continue;
2859             }
2860             *psock = csock;
2861 
2862             /* Create a thread to complete the client connection */
2863             if ( create_thread (&tid, DETACHED,
2864                                 serverConnect, psock, "serverConnect") )
2865             {
2866                 logmsg(_("HHCSH061E serverConnect create_thread: %s\n"),
2867                         strerror(HSO_errno));
2868                 close_socket (csock);
2869             }
2870 
2871         } /* end if(rsock) */
2872 
2873 
2874     } /* end while */
2875 
2876     /* Close the listening sockets */
2877     close_socket (lsock);
2878 #if defined( HAVE_SYS_UN_H )
2879     if (usock >= 0)
2880     {
2881         close_socket (usock);
2882         unlink(userver.sun_path);
2883     }
2884 #endif
2885 
2886     sysblk.shrdtid = 0;
2887 
2888     return NULL;
2889 
2890 } /* end function shared_server */
2891 
2892 /*-------------------------------------------------------------------
2893  * Shared device command processor
2894  *-------------------------------------------------------------------*/
shared_cmd(int argc,char * argv[],char * cmdline)2895 DLL_EXPORT int shared_cmd(int argc, char *argv[], char *cmdline)
2896 {
2897     char buf[256];
2898     char *kw, *op, c;
2899 
2900     UNREFERENCED(cmdline);
2901 
2902     /* Get keyword and operand */
2903     if (argc != 2 || strlen(argv[1]) > 255)
2904     {
2905         logmsg (_("HHCSH062E Invalid or missing argument 1\n"));
2906         return 0;
2907     }
2908     strcpy (buf, argv[1]);
2909     kw = strtok (buf, "=");
2910     op = strtok (NULL, " \t");
2911 
2912     if (kw == NULL)
2913     {
2914         logmsg (_("HHCSH063E Invalid or missing keyword 2\n"));
2915         return 0;
2916     }
2917 
2918     if (strcasecmp(kw, "trace") == 0)
2919     {
2920         int n;
2921         SHRD_TRACE *s, *p, *x, *i;
2922         s = sysblk.shrdtrace;
2923         p = sysblk.shrdtracep;
2924         x = sysblk.shrdtracex;
2925         n = sysblk.shrdtracen;
2926 
2927         /* Get a new trace table if an operand was specified */
2928         if (op)
2929         {
2930             if (sscanf (op, "%d%c", &n, &c) != 1)
2931             {
2932                 logmsg (_("HHCSH064E Invalid or missing value %s\n"),op);
2933                 return 0;
2934             }
2935             if (s != NULL)
2936             {
2937                 sysblk.shrdtrace = sysblk.shrdtracex = sysblk.shrdtracep = NULL;
2938                 SLEEP (1);
2939                 free (s);
2940             }
2941             sysblk.shrdtrace = sysblk.shrdtracex = sysblk.shrdtracep = NULL;
2942             sysblk.shrdtracen = 0;
2943             if (n > 0)
2944             {
2945                 s = calloc (sizeof(SHRD_TRACE), n);
2946                 if (s == NULL)
2947                 {
2948                     logmsg (_("HHCSH065E calloc() size=%d: %s\n"),
2949                             sizeof(SHRD_TRACE) * n, strerror(errno));
2950                     return 0;
2951                 }
2952                 sysblk.shrdtracen = n;
2953                 sysblk.shrdtrace = sysblk.shrdtracep = s;
2954                 sysblk.shrdtracex = s + n;
2955             }
2956             return 0;
2957         }
2958         /* Print the trace table */
2959         sysblk.shrdtrace = sysblk.shrdtracex = sysblk.shrdtracep = NULL;
2960         i = p;
2961         SLEEP(1);
2962         do {
2963             if (i[0] != '\0') logmsg ("%s",(char *)i);
2964             if (++i >= x) i = s;
2965         } while (i != p);
2966         memset (s, 0, n * sizeof(SHRD_TRACE));
2967         sysblk.shrdtrace = s;
2968         sysblk.shrdtracep = s;
2969         sysblk.shrdtracex = x;
2970         sysblk.shrdtracen = n;
2971     }
2972     else
2973     {
2974         logmsg (_("HHCSH066E Invalid or missing keyword %s\n"), kw);
2975         return 0;
2976     }
2977     return 0;
2978 }
2979 
2980 DEVHND shared_ckd_device_hndinfo = {
2981         &shared_ckd_init,              /* Device Initialisation      */
2982         &ckddasd_execute_ccw,          /* Device CCW execute         */
2983         &shared_ckd_close,             /* Device Close               */
2984         &ckddasd_query_device,         /* Device Query               */
2985         &shared_start,                 /* Device Start channel pgm   */
2986         &shared_end,                   /* Device End channel pgm     */
2987         &shared_start,                 /* Device Resume channel pgm  */
2988         &shared_end,                   /* Device Suspend channel pgm */
2989         &shared_ckd_read,              /* Device Read                */
2990         &shared_ckd_write,             /* Device Write               */
2991         &shared_used,                  /* Device Query used          */
2992         &shared_reserve,               /* Device Reserve             */
2993         &shared_release,               /* Device Release             */
2994         NULL,                          /* Device Attention           */
2995         NULL,                          /* Immediate CCW Codes        */
2996         NULL,                          /* Signal Adapter Input       */
2997         NULL,                          /* Signal Adapter Output      */
2998         &ckddasd_hsuspend,             /* Hercules suspend           */
2999         &ckddasd_hresume               /* Hercules resume            */
3000 };
3001 
3002 DEVHND shared_fba_device_hndinfo = {
3003         &shared_fba_init,              /* Device Initialisation      */
3004         &fbadasd_execute_ccw,          /* Device CCW execute         */
3005         &shared_fba_close,             /* Device Close               */
3006         &fbadasd_query_device,         /* Device Query               */
3007         &shared_start,                 /* Device Start channel pgm   */
3008         &shared_end,                   /* Device End channel pgm     */
3009         &shared_start,                 /* Device Resume channel pgm  */
3010         &shared_end,                   /* Device Suspend channel pgm */
3011         &shared_ckd_read,              /* Device Read                */
3012         &shared_ckd_write,             /* Device Write               */
3013         &shared_used,                  /* Device Query used          */
3014         &shared_reserve,               /* Device Reserve             */
3015         &shared_release,               /* Device Release             */
3016         NULL,                          /* Device Attention           */
3017         NULL,                          /* Immediate CCW Codes        */
3018         NULL,                          /* Signal Adapter Input       */
3019         NULL,                          /* Signal Adapter Output      */
3020         &fbadasd_hsuspend,             /* Hercules suspend           */
3021         &fbadasd_hresume               /* Hercules resume            */
3022 };
3023 
3024 #else
3025 
shared_update_notify(DEVBLK * dev,int block)3026 int shared_update_notify (DEVBLK *dev, int block)
3027 {
3028  UNREFERENCED(dev);
3029  UNREFERENCED(block);
3030  return 0;
3031 }
shared_ckd_init(DEVBLK * dev,int argc,BYTE * argv[])3032 int shared_ckd_init (DEVBLK *dev, int argc, BYTE *argv[] )
3033 {
3034  UNREFERENCED(dev);
3035  UNREFERENCED(argc);
3036  UNREFERENCED(argv);
3037  return -1;
3038 }
shared_fba_init(DEVBLK * dev,int argc,BYTE * argv[])3039 int shared_fba_init (DEVBLK *dev, int argc, BYTE *argv[] )
3040 {
3041  UNREFERENCED(dev);
3042  UNREFERENCED(argc);
3043  UNREFERENCED(argv);
3044  return -1;
3045 }
shared_server(void * arg)3046 void *shared_server (void *arg)
3047 {
3048  UNREFERENCED(arg);
3049  logmsg (_("HHCSH999E OPTION_SHARED_DEVICES not defined"));
3050  return NULL;
3051 }
3052 int shared_cmd(int argc, char *argv[], char *cmdline);
3053  UNREFERENCED(cmdline);
3054  UNREFERENCED(argc);
3055  UNREFERENCED(argv);
3056  logmsg (_("HHCSH999E OPTION_SHARED_DEVICES not defined"));
3057  return 0;
3058 }
3059 #endif /*defined(OPTION_SHARED_DEVICES)*/
3060