This source file includes following definitions.
- tun_alloc
- alloc_buffer
- fnpuv_associated_brk
- fnpuv_associated_readcb
- fnpuv_3270_readcb
- fnpuv_unassociated_readcb
- fuv_close_cb
- close_connection
- fuv_read_cb
- fuv_write_cb
- fuv_write_3270_cb
- fnpuv_start_write_3270_actual
- fnpuv_start_write_actual
- fnpuv_start_write
- fnpuv_start_3270_write
- fnpuv_start_writestr
- fnpuv_send_eor
- fnpuv_recv_eor
- fnpuv_read_start
- fnpuv_read_stop
- on_new_connection
- fnpuvInit
- fnpuvProcessEvent
- on_dialout_connect
- fnpuv_dial_out
- fnpuv_open_slave
- processPacketInput
- fnoTUNProcessLine
- fnpTUNProcessEvent
- fnpuv3270Poll
- on_new_3270_connection
- fnpuv3270Init
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 
  33 
  34 
  35 
  36 
  37 
  38 
  39 
  40 
  41 
  42 
  43 
  44 
  45 
  46 
  47 
  48 
  49 
  50 
  51 
  52 
  53 
  54 
  55 
  56 
  57 
  58 
  59 
  60 
  61 
  62 
  63 
  64 
  65 
  66 
  67 
  68 
  69 
  70 
  71 
  72 
  73 
  74 
  75 
  76 
  77 
  78 
  79 
  80 
  81 
  82 
  83 
  84 
  85 
  86 
  87 
  88 
  89 
  90 
  91 
  92 
  93 
  94 
  95 
  96 
  97 
  98 
  99 
 100 
 101 
 102 
 103 
 104 
 105 
 106 
 107 
 108 
 109 
 110 
 111 
 112 
 113 
 114 
 115 
 116 
 117 
 118 
 119 
 120 
 121 
 122 
 123 
 124 
 125 
 126 
 127 
 128 
 129 
 130 
 131 
 132 
 133 
 134 
 135 
 136 
 137 
 138 
 139 
 140 
 141 
 142 
 143 
 144 
 145 
 146 
 147 
 148 
 149 
 150 
 151 
 152 
 153 
 154 
 155 
 156 #ifdef TUN
 157 
 158 
 159 
 160 
 161 
 162 
 163 
 164 
 165 
 166 
 167 
 168 
 169 
 170 
 171 
 172 
 173 
 174 
 175 
 176 
 177 
 178 
 179 #endif
 180 
 181 #define ASSUME0 0
 182 
 183 #include <stdio.h>
 184 #include <stdlib.h>
 185 #include <unistd.h>
 186 #include <ctype.h>
 187 #include <signal.h>
 188 #ifdef TUN
 189 # include <string.h>
 190 # include <fcntl.h>
 191 # include <errno.h>
 192 # include <sys/ioctl.h>
 193 # include <sys/types.h>
 194 # include <sys/stat.h>
 195 # include <netinet/in.h>
 196 # include <sys/socket.h>
 197 # include <linux/if.h>
 198 # include <linux/if_tun.h>
 199 #endif
 200 
 201 #include "dps8.h"
 202 #include "dps8_scu.h"
 203 #include "dps8_sys.h"
 204 #include "dps8_iom.h"
 205 #include "dps8_cable.h"
 206 #include "dps8_cpu.h"
 207 #include "dps8_fnp2.h"
 208 #include "dps8_utils.h"
 209 #include "fnpuv.h"
 210 #include "fnptelnet.h"
 211 
 212 #ifdef TESTING
 213 # undef realloc
 214 # undef FREE
 215 # define FREE(p) free(p)
 216 # define realloc trealloc
 217 #endif 
 218 
 219 #define USE_REQ_DATA
 220 
 221 
 222 #define DEFAULT_BACKLOG 1024
 223 
 224 #ifdef TUN
 225 static int tun_alloc (char * dev)
     
 226   {
 227     struct ifreq ifr;
 228     int fd, err;
 229 
 230     if ((fd = open ("/dev/net/tun", O_RDWR)) < 0)
 231       
 232       return fd;
 233 
 234     memset (& ifr, 0,  sizeof (ifr));
 235 
 236     
 237 
 238 
 239 
 240 
 241 
 242 
 243     ifr.ifr_flags = IFF_TUN;
 244     if (* dev)
 245       strncpy (ifr.ifr_name, dev, IFNAMSIZ);
 246 
 247     if ((err = ioctl (fd, TUNSETIFF, (void *) & ifr)) < 0)
 248       {
 249         close (fd);
 250         return err;
 251       }
 252     strcpy (dev, ifr.ifr_name);
 253     return fd;
 254   }
 255 #endif
 256 
 257 
 258 
 259 
 260 
 261 static void alloc_buffer (UNUSED uv_handle_t * handle, size_t suggested_size,
     
 262                           uv_buf_t * buf)
 263  {
 264 
 265 #if !defined ( __clang_analyzer__ )
 266     * buf = uv_buf_init ((char *) malloc (suggested_size), (uint) suggested_size);
 267 #endif 
 268   }
 269 
 270 void fnpuv_associated_brk (uv_tcp_t * client)
     
 271   {
 272     if (! client || uv_is_closing ((uv_handle_t *) client))
 273       return;
 274     if (! client->data)
 275       {
 276         sim_warn ("fnpuv_associated_brk bad client data\r\n");
 277         return;
 278       }
 279     uvClientData * p = (uvClientData *) client->data;
 280     uint fnpno = p -> fnpno;
 281     uint lineno = p -> lineno;
 282     struct t_line * linep = & fnpData.fnpUnitData[fnpno].MState.line[lineno];
 283     
 284     
 285     
 286     linep->accept_input = 1;
 287     linep->line_break=true;
 288   }
 289 
 290 
 291 
 292 
 293 void fnpuv_associated_readcb (uv_tcp_t * client,
     
 294                            ssize_t nread,
 295                            unsigned char * buf)
 296   {
 297     processLineInput (client, buf, nread);
 298   }
 299 
 300 void fnpuv_3270_readcb (uv_tcp_t * client,
     
 301                            ssize_t nread,
 302                            unsigned char * buf)
 303   {
 304     process3270Input (client, buf, nread);
 305   }
 306 
 307 
 308 
 309 
 310 void fnpuv_unassociated_readcb (uv_tcp_t * client,
     
 311                            ssize_t nread,
 312                            unsigned char * buf)
 313   {
 314     
 315     processUserInput (client, buf, nread);
 316   }
 317 
 318 static void fuv_close_cb (uv_handle_t * stream)
     
 319   {
 320     FREE (stream);
 321   }
 322 
 323 
 324 
 325 void close_connection (uv_stream_t* stream)
     
 326   {
 327     if (! stream)
 328       {
 329         sim_warn ("close_connection bad client data\r\n");
 330         return;
 331       }
 332     uvClientData * p = (uvClientData *) stream->data;
 333 
 334     
 335     
 336     
 337     if (p)
 338       {
 339         
 340         
 341         if (p->assoc)
 342           {
 343             struct t_line * linep = & fnpData.fnpUnitData[p->fnpno].MState.line[p->lineno];
 344             if (linep->service  == service_3270)
 345              {
 346                
 347                sim_printf ("\r[FNP emulation: TN3270 %d.%d DISCONNECT]\r\n", ASSUME0, p->stationNo);
 348              }
 349             else
 350               {
 351                 sim_printf ("\r[FNP emulation: DISCONNECT %c.d%03d]\r\n", p->fnpno+'a', p->lineno);
 352 #ifdef DISC_DELAY
 353                 linep -> line_disconnected = DISC_DELAY;
 354 #else
 355                 linep -> line_disconnected = true;
 356 #endif
 357                 linep -> listen = false;
 358                 if (linep->inBuffer)
 359                   FREE (linep->inBuffer);
 360                 linep->inBuffer = NULL;
 361                 linep->inSize   = 0;
 362                 linep->inUsed   = 0;
 363                 linep->nPos     = 0;
 364               }
 365             if (linep->line_client)
 366               {
 367                 
 368                 
 369                 linep->line_client = NULL;
 370               }
 371           }
 372         else 
 373           {
 374             sim_printf ("\r[FNP emulation: DISCONNECT]\r\n");
 375           }
 376         
 377         if (p->telnetp)
 378           {
 379             telnet_free (p->telnetp);
 380             
 381             
 382             p->telnetp = NULL;
 383           }
 384         if (((uvClientData *) stream->data)->ttype)
 385           FREE (((uvClientData *) stream->data)->ttype);
 386         FREE (stream->data);
 387         stream->data = NULL;
 388       } 
 389     if (! uv_is_closing ((uv_handle_t *) stream))
 390       uv_close ((uv_handle_t *) stream, fuv_close_cb);
 391   }
 392 
 393 
 394 
 395 
 396 
 397 
 398 
 399 static void fuv_read_cb (uv_stream_t* stream,
     
 400                          ssize_t nread,
 401                          const uv_buf_t* buf)
 402   {
 403     if (nread < 0)
 404       {
 405         
 406           {
 407             close_connection (stream);
 408           }
 409       }
 410     else if (nread > 0)
 411       {
 412         if (! stream)
 413           {
 414             sim_warn ("fuv_read_cb bad client data\r\n");
 415             return;
 416           }
 417         uvClientData * p = (uvClientData *) stream->data;
 418         if (p)
 419           {
 420             if (p->telnetp)
 421               {
 422                 telnet_recv (p->telnetp, buf->base, (size_t) nread);
 423               }
 424             else
 425               {
 426 
 427                 (* p->read_cb) ((uv_tcp_t *) stream, nread, (unsigned char *) buf->base);
 428 
 429 
 430 
 431 
 432 
 433 
 434 
 435 
 436 
 437 
 438 
 439               }
 440           }
 441       }
 442 
 443     if (buf->base)
 444         free (buf->base);
 445   }
 446 
 447 
 448 
 449 
 450 
 451 
 452 
 453 
 454 static void fuv_write_cb (uv_write_t * req, int status)
     
 455   {
 456     if (status < 0)
 457       {
 458         if (status == -ECONNRESET || status == -ECANCELED ||
 459             status == -EPIPE)
 460           {
 461             
 462           }
 463         else
 464           {
 465             sim_warn ("fuv_write_cb status %d (%s)\n", -status, strerror (-status));
 466           }
 467 
 468         
 469         close_connection (req->handle);
 470       }
 471 
 472 #ifdef USE_REQ_DATA
 473 
 474     FREE (req->data);
 475 #else
 476     unsigned int nbufs = req->nbufs;
 477     uv_buf_t * bufs = req->bufs;
 478     
 479 
 480 
 481 
 482 
 483 
 484     for (unsigned int i = 0; i < nbufs; i ++)
 485       {
 486         if (bufs && bufs[i].base)
 487           {
 488 
 489             FREE (bufs[i].base);
 490             
 491           }
 492         if (req->bufsml[i].base)
 493           {
 494 
 495             FREE (req->bufsml[i].base);
 496           }
 497       }
 498 #endif
 499 
 500     
 501 
 502     FREE (req);
 503   }
 504 
 505 
 506 
 507 
 508 
 509 
 510 
 511 
 512 static void fuv_write_3270_cb (uv_write_t * req, int status) {
     
 513     uv_tcp_t * client = (uv_tcp_t *) req->handle;
 514     fuv_write_cb (req, status);
 515     set_3270_write_complete (client);
 516   }
 517 
 518 
 519 
 520 static void fnpuv_start_write_3270_actual (UNUSED uv_tcp_t * client, unsigned char * data, ssize_t datalen)
     
 521   {
 522 #ifdef TESTING
 523 sim_printf ("fnpuv_start_write_3270_actual\r\n");
 524 #endif
 525 
 526 
 527 
 528 
 529 
 530 
 531 
 532 
 533 
 534 
 535 
 536 
 537 
 538 
 539 
 540 
 541 
 542 
 543 
 544 
 545 
 546 
 547 
 548     
 549 
 550     uint stn_no;
 551     for (stn_no = 0; stn_no < ADDR_MAP_ENTRIES; stn_no ++)
 552       if (addr_map [stn_no] == fnpData.ibm3270ctlr[ASSUME0].selDevChar)
 553         break;
 554     if (stn_no >= ADDR_MAP_ENTRIES)
 555       {
 556         sim_printf ("fnpuv_start_write_3270_actual couldn't find selDevChar %02x\r\n", (unsigned int) fnpData.ibm3270ctlr[ASSUME0].selDevChar);
 557         return;
 558       }
 559     uv_tcp_t * stn_client = fnpData.ibm3270ctlr[ASSUME0].stations[stn_no].client;
 560     if (! stn_client || uv_is_closing ((uv_handle_t *) stn_client))
 561       return;
 562 
 563     
 564 
 565 #if !defined ( __clang_analyzer__ )
 566     uv_write_t * req = (uv_write_t *) malloc (sizeof (uv_write_t));
 567     if (!req)
 568       {
 569         fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
 570                  __func__, __FILE__, __LINE__);
 571 # if defined(USE_BACKTRACE)
 572 #  ifdef SIGUSR2
 573         (void)raise(SIGUSR2);
 574          
 575 #  endif 
 576 # endif 
 577         abort();
 578       }
 579     
 580     memset (req, 0, sizeof (uv_write_t));
 581     uv_buf_t buf = uv_buf_init ((char *) malloc ((unsigned long) datalen), (uint) datalen);
 582 
 583 # ifdef USE_REQ_DATA
 584     req->data = buf.base;
 585 # endif
 586 
 587     memcpy (buf.base, data, (unsigned long) datalen);
 588     int ret = uv_write (req, (uv_stream_t *) stn_client, & buf, 1, fuv_write_3270_cb);
 589 
 590 
 591 
 592 
 593     if (ret < 0 && ret != -EBADF)
 594       sim_printf ("\r[FNP emulation: uv_write returned %d]\r\n", ret);
 595 #endif 
 596   }
 597 
 598 void fnpuv_start_write_actual (uv_tcp_t * client, unsigned char * data, ssize_t datalen)
     
 599   {
 600     if (! client || uv_is_closing ((uv_handle_t *) client))
 601       return;
 602 
 603 #if !defined ( __clang_analyzer__ )
 604     uv_write_t * req = (uv_write_t *) malloc (sizeof (uv_write_t));
 605     if (!req)
 606       {
 607         fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
 608                  __func__, __FILE__, __LINE__);
 609 # if defined(USE_BACKTRACE)
 610 #  ifdef SIGUSR2
 611         (void)raise(SIGUSR2);
 612          
 613 #  endif 
 614 # endif 
 615         abort();
 616       }
 617     
 618     memset (req, 0, sizeof (uv_write_t));
 619     uv_buf_t buf = uv_buf_init ((char *) malloc ((unsigned long) datalen), (uint) datalen);
 620 
 621 # ifdef USE_REQ_DATA
 622     req->data = buf.base;
 623 # endif
 624 
 625     memcpy (buf.base, data, (unsigned long) datalen);
 626     int ret = uv_write (req, (uv_stream_t *) client, & buf, 1, fuv_write_cb);
 627 
 628 
 629 
 630 
 631     if (ret < 0 && ret != -EBADF)
 632       sim_printf ("\r[FNP emulation: uv_write returned %d]\r\n", ret);
 633 #endif 
 634   }
 635 
 636 
 637 
 638 
 639 
 640 void fnpuv_start_write (uv_tcp_t * client, unsigned char * data, ssize_t datalen)
     
 641   {
 642     if (! client || uv_is_closing ((uv_handle_t *) client))
 643       return;
 644     uvClientData * p = (uvClientData *) client->data;
 645     if (! p) 
 646       return;
 647     if (!p->telnetp)
 648       {
 649         sim_warn ("telnetp NULL; dropping fnpuv_start_write()\n");
 650         return;
 651       }
 652     telnet_send (p->telnetp, (char *) data, (size_t) datalen);
 653   }
 654 
 655 void fnpuv_start_3270_write (uv_tcp_t * client, unsigned char * data, ssize_t datalen)
     
 656   {
 657     if (! client || uv_is_closing ((uv_handle_t *) client) || ! client->data)
 658       return;
 659     uvClientData * p = (uvClientData *) client->data;
 660     if (! p) 
 661       return;
 662 #ifdef TESTING
 663 sim_printf ("fnpuv_start_3270_write\r\n");
 664 #endif
 665 
 666 
 667 
 668 
 669 
 670 
 671 
 672 
 673 
 674 
 675 
 676 
 677 
 678 
 679 
 680 
 681 
 682 
 683 
 684 
 685 
 686 
 687 
 688     
 689     
 690     
 691 
 692     if (datalen == 1 && data [0] == 0x37) 
 693       {
 694 #ifdef TESTING
 695 sim_printf ("fnpuv: detected EOT\r\n");
 696 #endif
 697         fnpuv_send_eor (client);
 698         return;
 699       }
 700 
 701     unsigned char * actual_data_start = data;
 702     unsigned long actual_datalen = (unsigned long) datalen;
 703     
 704     if (data [datalen - 1] == 0x03) 
 705       {
 706         actual_datalen --;
 707         
 708       }
 709     if (data [0] == 0x02) 
 710       {
 711         actual_data_start ++;
 712         actual_datalen --;
 713         if (data [1] == 0x27) 
 714           {
 715             actual_data_start ++;
 716             actual_datalen --;
 717           }
 718       }
 719 
 720     telnet_send (p->telnetp, (char *) actual_data_start, (size_t) actual_datalen);
 721     
 722       
 723   }
 724 
 725 
 726 
 727 void fnpuv_start_writestr (uv_tcp_t * client, unsigned char * data)
     
 728   {
 729     
 730     if (! client || uv_is_closing ((uv_handle_t *) client))
 731       return;
 732     if (! client->data)
 733       {
 734         sim_warn ("fnpuv_start_writestr bad client data\r\n");
 735         return;
 736       }
 737     uvClientData * p = client->data;
 738     (* p->write_cb) (client, data, (ssize_t) strlen ((char *) data));
 739   }
 740 
 741 void fnpuv_send_eor (uv_tcp_t * client)
     
 742   {
 743     if (! client || uv_is_closing ((uv_handle_t *) client))
 744       return;
 745     if (! client->data)
 746       {
 747         sim_warn ("fnpuv_send_eor bad client data\r\n");
 748         return;
 749       }
 750     uvClientData * p = (uvClientData *) client->data;
 751     ltnEOR (p->telnetp);
 752     
 753     
 754   }
 755 
 756 void fnpuv_recv_eor (uv_tcp_t * client)
     
 757   {
 758     fnpRecvEOR (client);
 759   }
 760 
 761 
 762 
 763 
 764 
 765 void fnpuv_read_start (uv_tcp_t * client)
     
 766   {
 767     if (! client || uv_is_closing ((uv_handle_t *) client))
 768       return;
 769     uv_read_start ((uv_stream_t *) client, alloc_buffer, fuv_read_cb);
 770   }
 771 
 772 
 773 
 774 
 775 
 776 void fnpuv_read_stop (uv_tcp_t * client)
     
 777   {
 778     if (! client || uv_is_closing ((uv_handle_t *) client))
 779       return;
 780     uv_read_stop ((uv_stream_t *) client);
 781   }
 782 
 783 
 784 
 785 
 786 
 787 static void on_new_connection (uv_stream_t * server, int status)
     
 788   {
 789     if (status < 0)
 790       {
 791         sim_printf ("\r[FNP emulation: new connection error: %s]\r\n", uv_strerror (status));
 792         
 793         return;
 794       }
 795 
 796     uv_tcp_t * client = (uv_tcp_t *) malloc (sizeof (uv_tcp_t));
 797     if (!client)
 798       {
 799         fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
 800                  __func__, __FILE__, __LINE__);
 801 #if defined(USE_BACKTRACE)
 802 # ifdef SIGUSR2
 803         (void)raise(SIGUSR2);
 804          
 805 # endif 
 806 #endif 
 807         abort();
 808       }
 809     uv_tcp_init (fnpData.loop, client);
 810     if (uv_accept (server, (uv_stream_t *) client) != 0)
 811       {
 812         uv_close ((uv_handle_t *) client, fuv_close_cb);
 813         return;
 814       }
 815 
 816     
 817     
 818     if (server->data)
 819       {
 820         uvClientData * p = (uvClientData *) server->data;
 821         struct t_line * linep = & fnpData.fnpUnitData[p->fnpno].MState.line[p->lineno];
 822 
 823         
 824         if (linep->line_client)
 825           {
 826             uv_close ((uv_handle_t *) client, fuv_close_cb);
 827 # ifdef TESTING
 828 sim_printf ("\r[FNP emulation: dropping 2nd slave]\r\n");
 829 # endif
 830             return;
 831           }
 832 
 833         linep->line_client = client;
 834       }
 835 
 836     struct sockaddr name;
 837     int namelen = sizeof (name);
 838     uv_tcp_nodelay (client,1);
 839     int ret = uv_tcp_getpeername (client, & name, & namelen);
 840     if (ret < 0)
 841       {
 842         sim_printf ("\r[FNP emulation: CONNECT; addr err %d]\r\n", ret);
 843       }
 844     else
 845       {
 846         struct sockaddr_in * p = (struct sockaddr_in *) & name;
 847         sim_printf ("\r[FNP emulation: CONNECT %s]\r\n", inet_ntoa (p -> sin_addr));
 848       }
 849 
 850     uvClientData * p = (uvClientData *) malloc (sizeof (uvClientData));
 851     if (! p)
 852       {
 853          fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
 854                   __func__, __FILE__, __LINE__);
 855 #if defined(USE_BACKTRACE)
 856 # ifdef SIGUSR2
 857         (void)raise(SIGUSR2);
 858          
 859 # endif 
 860 #endif 
 861         abort();
 862       }
 863     client->data       = p;
 864     p->assoc           = false;
 865     p->nPos            = 0;
 866     p->ttype           = NULL;
 867     p->write_actual_cb = fnpuv_start_write_actual;
 868     
 869     if (! server->data)
 870       {
 871         p->read_cb  = fnpuv_unassociated_readcb;
 872         p->write_cb = fnpuv_start_write;
 873         p->telnetp  = ltnConnect (client);
 874 
 875         if (! p->telnetp)
 876           {
 877              sim_warn ("ltnConnect failed\n");
 878              return;
 879           }
 880       }
 881     else
 882       {
 883         p->read_cb       = fnpuv_associated_readcb;
 884         p->write_cb      = fnpuv_start_write_actual;
 885         p->telnetp       = NULL;
 886         uvClientData * q = (uvClientData *) server->data;
 887         p->fnpno         = q->fnpno;
 888         p->lineno        = q->lineno;
 889         p->assoc         = true;
 890       }
 891     fnpuv_read_start (client);
 892     if (! server->data)
 893       fnpConnectPrompt (client);
 894     else
 895       {
 896         uvClientData * p = (uvClientData *) server->data;
 897         struct t_line * linep = & fnpData.fnpUnitData[p->fnpno].MState.line[p->lineno];
 898         if (linep->lineType == 0) 
 899           linep->lineType = 1; 
 900         linep->accept_new_terminal = true;
 901         reset_line (linep);
 902       }
 903   }
 904 
 905 
 906 
 907 
 908 
 909 int fnpuvInit (int telnet_port, char * telnet_address)
     
 910   {
 911     
 912     
 913     
 914     if (fnpData.du_server_inited)
 915       {
 916         sim_printf ("\r[FNP emulation: FNP already initialized]\r\n");
 917         return 1;
 918       }
 919 
 920     if (! fnpData.loop)
 921       fnpData.loop = uv_default_loop ();
 922 
 923     
 924     fnpData.loop = uv_default_loop ();
 925     uv_tcp_init (fnpData.loop, & fnpData.du_server);
 926 
 927 
 928 
 929 
 930     
 931     fnpData.du_server.data = NULL;
 932 
 933     
 934     struct sockaddr_in addr;
 935     uv_ip4_addr (telnet_address, telnet_port, & addr);
 936     uv_tcp_bind (& fnpData.du_server, (const struct sockaddr *) & addr, 0);
 937     int r = uv_listen ((uv_stream_t *) & fnpData.du_server, DEFAULT_BACKLOG,
 938                        on_new_connection);
 939     if (r)
 940      {
 941         sim_printf ("\r[FNP emulation: listen error: %s:%ld: %s]\r\n", telnet_address, (long) telnet_port, uv_strerror (r));
 942         return 1;
 943      }
 944     fnpData.du_server_inited = true;
 945     sim_printf ("\r[FNP emulation: TELNET server listening on %s:%ld]\r\n", telnet_address, (long) telnet_port);
 946     return 0;
 947   }
 948 
 949 
 950 
 951 void fnpuvProcessEvent (void)
     
 952   {
 953     
 954     
 955     
 956     
 957 
 958     
 959     
 960     
 961     if (! fnpData.loop)
 962       return;
 963      uv_run (fnpData.loop, UV_RUN_NOWAIT);
 964   }
 965 
 966 
 967 
 968 
 969 
 970 static void on_dialout_connect (uv_connect_t * server, int status)
     
 971   {
 972     sim_printf ("\r[FNP emulation: dialout connect]\r\n");
 973     uvClientData * p = (uvClientData *) server->handle->data;
 974     
 975     if (! p)
 976       {
 977          sim_printf ("\r[FNP emulation: NOTE: on_dialout_connect called with data == NULL]\r\n");
 978          return;
 979       }
 980     struct t_line * linep = & fnpData.fnpUnitData[p->fnpno].MState.line[p->lineno];
 981     if (status < 0)
 982       {
 983         sim_printf ("\r[FNP emulation: dialout connection error: %s]\r\n", uv_strerror (status));
 984         
 985         
 986         linep->acu_dial_failure = true;
 987         return;
 988       }
 989 
 990     uv_read_start ((uv_stream_t *) linep->line_client, alloc_buffer, fuv_read_cb);
 991     linep->listen = true;
 992     if (linep->lineType == 0) 
 993       linep->lineType = 1; 
 994     linep->accept_new_terminal = true;
 995     linep->was_CR              = false;
 996     linep->line_client->data   = p;
 997     if (p->telnetp)
 998       {
 999         ltnDialout (p->telnetp);
1000       }
1001   }
1002 
1003 
1004 
1005 
1006 
1007 void fnpuv_dial_out (uint fnpno, uint lineno, word36 d1, word36 d2, word36 d3)
     
1008   {
1009     if (! fnpData.loop)
1010       return;
1011     sim_printf ("\r[FNP emulation: received dial_out %c.h%03d %012llu %012llu %012llu]\r\n", fnpno+'a', lineno,
1012             (unsigned long long)d1, (unsigned long long)d2, (unsigned long long)d3);
1013     struct t_line * linep = & fnpData.fnpUnitData[fnpno].MState.line[lineno];
1014     uint d01   = (d1 >> 30) & 017;
1015     uint d02   = (d1 >> 24) & 017;
1016     uint d03   = (d1 >> 18) & 017;
1017     uint d04   = (d1 >> 12) & 017;
1018     uint d05   = (d1 >>  6) & 017;
1019     uint d06   = (d1 >>  0) & 017;
1020     uint d07   = (d2 >> 30) & 017;
1021     uint d08   = (d2 >> 24) & 017;
1022     uint d09   = (d2 >> 18) & 017;
1023     uint d10   = (d2 >> 12) & 017;
1024     uint d11   = (d2 >>  6) & 017;
1025     uint d12   = (d2 >>  0) & 017;
1026     uint flags = (d3 >> 30) & 017;
1027     uint p1    = (d3 >> 24) & 017;
1028     uint p2    = (d3 >> 18) & 017;
1029     uint p3    = (d3 >> 12) & 017;
1030     uint p4    = (d3 >>  6) & 017;
1031     uint p5    = (d3 >>  0) & 017;
1032 
1033     uint oct1  = d01 * 100 + d02 * 10 + d03;
1034     uint oct2  = d04 * 100 + d05 * 10 + d06;
1035     uint oct3  = d07 * 100 + d08 * 10 + d09;
1036     uint oct4  = d10 * 100 + d11 * 10 + d12;
1037 
1038     uint port  = ((((p1 * 10) + p2) * 10 + p3) * 10 + p4) * 10 + p5;
1039 
1040 
1041 
1042 #ifdef TUN
1043 
1044 #endif
1045 
1046 
1047 #ifdef TUN
1048     linep->is_tun = false;
1049     if (flags & 2)
1050       {
1051         if (linep->tun_fd <= 0)
1052           {
1053             char a_name [IFNAMSIZ] = "dps8m";
1054             linep->tun_fd = tun_alloc (a_name);
1055             if (linep->tun_fd < 0)
1056               {
1057                 sim_printf ("\r[FNP emulation: dialout TUN tun_alloc returned %d errno %d]\r\n", linep->tun_fd, errno);
1058                 return;
1059              }
1060             int flags = fcntl (linep->tun_fd, F_GETFL, 0);
1061             if (flags < 0)
1062               {
1063                 sim_printf ("\r[FNP emulation: dialout TUN F_GETFL returned < 0]\r\n");
1064                 return;
1065               }
1066             flags |= O_NONBLOCK;
1067             int ret = fcntl (linep->tun_fd, F_SETFL, flags);
1068             if (ret)
1069               {
1070                 sim_printf ("\r[FNP emulation: dialout TUN F_SETFL returned %d]\r\n", ret);
1071                 return;
1072               }
1073           }
1074           linep->is_tun = true;
1075           return;
1076         }
1077 #endif
1078 
1079 
1080 
1081     
1082     bool accept = true;
1083     uint32_t ip_addr = (uint32_t) ((oct1 << 24) | (oct2 << 16) | (oct3 << 8) | oct4);
1084     uint this_line = encodeline (fnpno, lineno);
1085     for (int i = 0; i < n_fw_entries; i ++)
1086       {
1087         struct fw_entry_s * p = fw_entries + i;
1088         if (this_line < p->line_0 || this_line > p->line_1)
1089           continue;
1090         if ((ip_addr & p->cidr_mask) != (p->ipaddr & p->cidr_mask))
1091           continue;
1092         accept = p->accept;
1093         break;
1094       }
1095 
1096     if (! accept)
1097       {
1098         sim_printf ("Dialout %c.d%03d denied\r\n", fnpno + 'a', lineno);
1099         linep->acu_dial_failure = true;
1100         return;
1101       }
1102 
1103     char ipaddr [256];
1104     sprintf (ipaddr, "%d.%d.%d.%d", oct1, oct2, oct3, oct4);
1105     sim_printf ("calling %s:%d\n", ipaddr,port);
1106 
1107     struct sockaddr_in dest;
1108     uv_ip4_addr(ipaddr, (int) port, &dest);
1109 
1110     linep->line_client = (uv_tcp_t *) malloc (sizeof (uv_tcp_t));
1111     if (!linep->line_client)
1112       {
1113         fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1114                  __func__, __FILE__, __LINE__);
1115 #if defined(USE_BACKTRACE)
1116 # ifdef SIGUSR2
1117         (void)raise(SIGUSR2);
1118          
1119 # endif 
1120 #endif 
1121         abort();
1122       }
1123     uv_tcp_init (fnpData.loop, linep->line_client);
1124 
1125     uvClientData * p = (uvClientData *) malloc (sizeof (uvClientData));
1126     if (! p)
1127       {
1128         fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1129                  __func__, __FILE__, __LINE__);
1130 #if defined(USE_BACKTRACE)
1131 # ifdef SIGUSR2
1132         (void)raise(SIGUSR2);
1133          
1134 # endif 
1135 #endif 
1136         abort();
1137       }
1138     p->assoc                 = true;
1139     p->read_cb               = fnpuv_associated_readcb;
1140     p->nPos                  = 0;
1141     p->ttype                 = NULL;
1142     p->fnpno                 = fnpno;
1143     p->lineno                = lineno;
1144     linep->line_client->data = p;
1145 
1146     if (flags & 1)
1147       {
1148         p->write_cb        = fnpuv_start_write;
1149         p->write_actual_cb = fnpuv_start_write_actual;
1150         p->telnetp         = ltnConnect (linep->line_client);
1151         if (! p->telnetp)
1152           {
1153               sim_warn ("ltnConnect failed\n");
1154           }
1155       }
1156     else
1157       {
1158         p->write_cb        = fnpuv_start_write_actual;
1159         p->write_actual_cb = fnpuv_start_write_actual;
1160         p->telnetp         = NULL; 
1161       }
1162 
1163     uv_tcp_connect (& linep->doConnect, linep->line_client, (const struct sockaddr *) & dest, on_dialout_connect);
1164   }
1165 
1166 
1167 
1168 
1169 
1170 
1171 
1172 
1173 
1174 
1175 
1176 
1177 
1178 
1179 
1180 
1181 
1182 
1183 
1184 
1185 
1186 
1187 
1188 void fnpuv_open_slave (uint fnpno, uint lineno)
     
1189   {
1190     if (! fnpData.loop)
1191       return;
1192     sim_printf ("\r[FNP emulation: fnpuv_open_slave %d.%d]\r\n", fnpno, lineno);
1193     struct t_line * linep = & fnpData.fnpUnitData[fnpno].MState.line[lineno];
1194 
1195     
1196     if (linep->server.data)
1197       return;
1198 
1199     uv_tcp_init (fnpData.loop, & linep->server);
1200 
1201     
1202     
1203     
1204     
1205 
1206     uvClientData * p = (uvClientData *) malloc (sizeof (uvClientData));
1207     if (! p)
1208       {
1209         fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1210                  __func__, __FILE__, __LINE__);
1211 #if defined(USE_BACKTRACE)
1212 # ifdef SIGUSR2
1213         (void)raise(SIGUSR2);
1214          
1215 # endif 
1216 #endif 
1217         abort();
1218       }
1219     p->assoc           = false;
1220     p->read_cb         = fnpuv_associated_readcb;
1221     p->write_cb        = fnpuv_start_write_actual;
1222     p->write_actual_cb = fnpuv_start_write_actual;
1223     p->nPos            = 0;
1224     p->ttype           = NULL;
1225     p->fnpno           = fnpno;
1226     p->lineno          = lineno;
1227     linep->server.data = p;
1228     linep->line_client = NULL;
1229 
1230     struct sockaddr_in addr;
1231     uv_ip4_addr (fnpData.telnet_address, linep->port, & addr);
1232     uv_tcp_bind (& linep->server, (const struct sockaddr *) & addr, 0);
1233     int r = uv_listen ((uv_stream_t *) & linep->server, DEFAULT_BACKLOG,
1234                        on_new_connection);
1235     if (r)
1236      {
1237         sim_printf ("\r[FNP emulation: listen error: %s:%ld: %s]\r\n", fnpData.telnet_address, (long) linep->port, uv_strerror (r));
1238      }
1239     sim_printf ("\r[FNP emulation: listening on %s:%ld]\r\n", fnpData.telnet_address, (long) linep->port);
1240 
1241 
1242 
1243 
1244 
1245 
1246 
1247 
1248 
1249 
1250 
1251 
1252 
1253 
1254 
1255 
1256 
1257 
1258 
1259 
1260 
1261 
1262 
1263 
1264 
1265 
1266 
1267 
1268 
1269 
1270 
1271 
1272 
1273 
1274 
1275 
1276 
1277 
1278 
1279 
1280 
1281 
1282 
1283 
1284 
1285 
1286 
1287 
1288 
1289 
1290 
1291 
1292   }
1293 
1294 #ifdef TUN
1295 static void processPacketInput (int fnpno, int lineno, unsigned char * buf, ssize_t nread)
     
1296   {
1297     
1298     
1299     
1300     if (fnpno >= N_FNP_UNITS_MAX || lineno >= MAX_LINES)
1301       {
1302         sim_printf ("\r[FNP emulation: processPacketInput bogus client data]\r\n");
1303         return;
1304       }
1305 
1306 
1307  
1308 
1309 
1310     struct t_line * linep = & fnpData.fnpUnitData[fnpno].MState.line[lineno];
1311     if (linep->inBuffer)
1312       {
1313         unsigned char * new = realloc (linep->inBuffer, (unsigned long) (linep->inSize + nread));
1314         if (! new)
1315           {
1316             fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1317                      __func__, __FILE__, __LINE__)
1318 # if defined(USE_BACKTRACE)
1319 #  ifdef SIGUSR2
1320             (void)raise(SIGUSR2);
1321              
1322 #  endif 
1323 # endif 
1324             abort();
1325           }
1326         memcpy (new + linep->inSize, buf, (unsigned long) nread);
1327         linep->inSize  += nread;
1328         linep->inBuffer = new;
1329       }
1330     else
1331       {
1332         linep->inBuffer = malloc ((unsigned long) nread);
1333         if (! linep->inBuffer)
1334           {
1335             fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1336                      __func__, __FILE__, __LINE__);
1337 # if defined(USE_BACKTRACE)
1338 #  ifdef SIGUSR2
1339             (void)raise(SIGUSR2);
1340              
1341 #  endif 
1342 # endif 
1343             abort();
1344           }
1345         memcpy (linep->inBuffer, buf, (unsigned long) nread);
1346         linep->inSize = (uint) nread;
1347         linep->inUsed = 0;
1348       }
1349 
1350   }
1351 
1352 static void fnoTUNProcessLine (int fnpno, int lineno, struct t_line * linep)
     
1353   {
1354 
1355     unsigned char buffer [1500 + 16];
1356     ssize_t nread = read (linep->tun_fd, buffer, sizeof (buffer));
1357     if (nread < 0)
1358       {
1359         
1360         
1361         
1362         if (errno == EAGAIN)
1363           return;
1364         sim_printf ("%ld %ld\n", (long) nread, (long) errno);
1365         return;
1366       }
1367 
1368 
1369 
1370     unsigned char xbufr [2 * (1500 + 16)];
1371     unsigned char bin2hex [16] = "0123456789ABCDEF";
1372 
1373     for (uint i = 0; i > nread; i ++)
1374       {
1375         xbufr [i * 2 + 0] = bin2hex [(buffer [i] >> 4) & 0xf];
1376         xbufr [i * 2 + 1] = bin2hex [(buffer [i] >> 0) & 0xf];
1377       }
1378      xbufr [nread * 2] = 0;
1379      processPacketInput (fnpno, lineno, xbufr, nread * 2 + 1);
1380 
1381 
1382 
1383 # define ip 4
1384     
1385     sim_printf("Read %ld bytes\n", (long) nread);
1386     sim_printf ("%02x %02x %02x %02x %02x %02x %02x %02x\n",
1387       buffer [0],  buffer [1],  buffer [2],  buffer [3],
1388       buffer [4],  buffer [5],  buffer [6],  buffer [7]);
1389     sim_printf ("%02x %02x %02x %02x %02x %02x %02x %02x\n",
1390       buffer [8],  buffer [9],  buffer [10], buffer [11],
1391       buffer [12], buffer [13], buffer [14], buffer [15]);
1392     uint version         =         (buffer [ip +  0] >> 4) & 0xf;
1393     uint ihl             =         (buffer [ip +  0]) & 0xf;
1394     uint payload_offset  =                  ip + ihl * 4;
1395     uint tos             =          buffer [ip +  1];
1396     uint tl              = ((uint) (buffer [ip +  2]) << 8) +
1397                                     buffer [ip +  3];
1398     uint id              = ((uint) (buffer [ip +  4]) << 8) +
1399                                     buffer [ip +  5];
1400     uint df              =         (buffer [ip +  6] & 0x40) ? 1 : 0;
1401     uint mf              =         (buffer [ip +  6] & 0x20) ? 1 : 0;
1402     uint fragment_offset = ((uint) (buffer [ip +  6] & 0x1f) << 8) +
1403                                     buffer [ip +  7];
1404     uint ttl             =          buffer [ip +  8];
1405     uint protocol        =          buffer [ip +  9];
1406     uint header_checksum = (((uint) buffer [ip + 10]) << 8) +
1407                                     buffer [ip + 11];
1408     uint source_address  = (((uint) buffer [ip + 12]) << 24) +
1409                            (((uint) buffer [ip + 13]) << 16) +
1410                            (((uint) buffer [ip + 14]) << 8) +
1411                                     buffer [ip + 15];
1412     uint dest_address    = (((uint) buffer [ip + 16]) << 24) +
1413                            (((uint) buffer [ip + 17]) << 16) +
1414                            (((uint) buffer [ip + 18]) << 8) +
1415                                     buffer [ip + 19];
1416     if (protocol == 1)
1417       {
1418         uint type = buffer [payload_offset + 0];
1419         if (type == 0x08)
1420           {
1421             sim_printf ("ICMP Echo Request %d.%d.%d.%d %d.%d.%d.%d\n",
1422               buffer [ip + 12], buffer [ip + 13], buffer [ip + 14], buffer [ip + 15],
1423               buffer [ip + 16], buffer [ip + 17], buffer [ip + 18], buffer [ip + 19]);
1424           }
1425         else
1426           {
1427             sim_printf ("ICMP 0x%02x\n", type);
1428             sim_printf ("%02x %02x %02x %02x %02x %02x %02x %02x\n",
1429               buffer [payload_offset + 0], buffer [payload_offset + 1], buffer [payload_offset + 2], buffer [payload_offset + 3],
1430               buffer [payload_offset + 4], buffer [payload_offset + 5], buffer [payload_offset + 6], buffer [payload_offset + 7]);
1431           }
1432       }
1433     if (protocol == 0x11)
1434       {
1435         sim_printf ("UDP\n");
1436 
1437       }
1438     else
1439       {
1440         sim_printf ("protocol %02x\n", protocol);
1441       }
1442   }
1443 
1444 void fnpTUNProcessEvent (void)
     
1445   {
1446     unint32 numunits = fnp_dev.numunits;
1447     for (int fnpno = 0; fnpno < numnumts; fnpno ++)
1448       {
1449         for (int lineno = 0; lineno < MAX_LINES; lineno ++)
1450           {
1451             struct t_line * linep = & fnpData.fnpUnitData[fnpno].MState.line[lineno];
1452             if (linep->is_tun)
1453               fnoTUNProcessLine (fnpno, lineno, linep);
1454           }
1455       }
1456   }
1457 #endif
1458 
1459 void fnpuv3270Poll (bool start)
     
1460   {
1461 
1462     fnpData.du3270_poll = start ? 100 : 0;
1463   }
1464 
1465 
1466 
1467 
1468 
1469 static void on_new_3270_connection (uv_stream_t * server, int status)
     
1470   {
1471     if (status < 0)
1472       {
1473         sim_printf ("\r[FNP emulation: TN3270 new connection error: %s]\r\n", uv_strerror (status));
1474         
1475         return;
1476       }
1477 
1478     uv_tcp_t * client = (uv_tcp_t *) malloc (sizeof (uv_tcp_t));
1479     if (!client)
1480       {
1481         fprintf(stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1482                 __func__, __FILE__, __LINE__);
1483 #if defined(USE_BACKTRACE)
1484 # ifdef SIGUSR2
1485         (void)raise(SIGUSR2);
1486          
1487 # endif 
1488 #endif 
1489         abort();
1490       }
1491 
1492     uv_tcp_init (fnpData.loop, client);
1493     if (uv_accept (server, (uv_stream_t *) client) != 0)
1494       {
1495         uv_close ((uv_handle_t *) client, fuv_close_cb);
1496         return;
1497       }
1498 
1499     
1500     uint stn_no;
1501     for (stn_no = 0; stn_no < IBM3270_STATIONS_MAX; stn_no ++)
1502       {
1503         if (fnpData.ibm3270ctlr[ASSUME0].stations[stn_no].client == NULL)
1504           break;
1505       }
1506     if (stn_no >= IBM3270_STATIONS_MAX)
1507       {
1508         
1509         uv_close ((uv_handle_t *) client, fuv_close_cb);
1510         return;
1511       }
1512 
1513     uint fnpno  = fnpData.ibm3270ctlr[ASSUME0].fnpno;
1514     uint lineno = fnpData.ibm3270ctlr[ASSUME0].lineno;
1515     
1516     fnpData.fnpUnitData[fnpno].MState.line[lineno].line_client = NULL;
1517 
1518     fnpData.ibm3270ctlr[ASSUME0].stations[stn_no].client = client;
1519 
1520     
1521     fnpData.ibm3270ctlr[ASSUME0].selDevChar = addr_map[stn_no];
1522 
1523     struct sockaddr name;
1524     int namelen = sizeof (name);
1525     int ret = uv_tcp_getpeername (client, & name, & namelen);
1526     if (ret < 0)
1527       {
1528         sim_printf ("\r[FNP emulation: CONNECT; addr err %d]\r\n", ret);
1529       }
1530     else
1531       {
1532         struct sockaddr_in * p = (struct sockaddr_in *) & name;
1533         sim_printf ("\r[FNP emulation: CONNECT %s]\r\n", inet_ntoa (p -> sin_addr));
1534       }
1535 
1536     uvClientData * p = (uvClientData *) malloc (sizeof (uvClientData));
1537     if (! p)
1538       {
1539          fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
1540                   __func__, __FILE__, __LINE__);
1541 #if defined(USE_BACKTRACE)
1542 # ifdef SIGUSR2
1543          (void)raise(SIGUSR2);
1544           
1545 # endif 
1546 #endif 
1547          abort();
1548       }
1549     client->data       = p;
1550     p->assoc           = false;
1551     p->fnpno           = fnpno;
1552     p->lineno          = lineno;
1553     p->nPos            = 0;
1554     p->ttype           = NULL;
1555     p->read_cb         = fnpuv_3270_readcb;
1556     p->write_cb        = fnpuv_start_3270_write;
1557     p->write_actual_cb = fnpuv_start_write_3270_actual;
1558     p->stationNo       = stn_no;
1559     p->telnetp         = ltnConnect3270 (client);
1560 
1561     if (! p->telnetp)
1562       {
1563         sim_warn ("ltnConnect3270 failed\n");
1564         return;
1565       }
1566     fnpuv_read_start (client);
1567     fnp3270ConnectPrompt (client);
1568        
1569        
1570        
1571        
1572        
1573        
1574        
1575        
1576        
1577        
1578        
1579        
1580        
1581        
1582        
1583        
1584        
1585        
1586        
1587        
1588        
1589        
1590        
1591        
1592        
1593        
1594        
1595        
1596        
1597        
1598        
1599        
1600        
1601        
1602        
1603        
1604   }
1605 
1606 int fnpuv3270Init (int telnet3270_port)
     
1607   {
1608     
1609     
1610     
1611     if (fnpData.du3270_server_inited)
1612       {
1613         sim_printf ("\r[FNP emulation: FNP already initialized]\r\n");
1614         return 1;
1615       }
1616     if (! fnpData.loop)
1617       fnpData.loop = uv_default_loop ();
1618     
1619     uv_tcp_init (fnpData.loop, & fnpData.du3270_server);
1620 
1621     
1622     fnpData.du3270_server.data = NULL;
1623 
1624     
1625     struct sockaddr_in addr;
1626     uv_ip4_addr (fnpData.telnet_address, telnet3270_port, & addr);
1627     uv_tcp_bind (& fnpData.du3270_server, (const struct sockaddr *) & addr, 0);
1628     int r = uv_listen ((uv_stream_t *) & fnpData.du3270_server, DEFAULT_BACKLOG,
1629                    on_new_3270_connection);
1630     if (r)
1631      {
1632         sim_printf ("\r[FNP emulation: listen error: %s:%ld: %s]\r\n", fnpData.telnet_address, (long) telnet3270_port, uv_strerror (r));
1633         return 1;
1634      }
1635     fnpData.du3270_server_inited = true;
1636     sim_printf ("\r[FNP emulation: TN3270 server listening on %s:%ld]\r\n", fnpData.telnet_address, (long) telnet3270_port);
1637     fnpuv3270Poll (false);
1638     return 0;
1639   }