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 }