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